MySQL數(shù)據(jù)庫事務(wù)的示例分析

小編給大家分享一下MySQL數(shù)據(jù)庫事務(wù)的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)是一家專業(yè)從事成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司。作為專業(yè)網(wǎng)站建設(shè)公司,創(chuàng)新互聯(lián)依托的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營經(jīng)驗(yàn),為您提供專業(yè)的成都網(wǎng)站建設(shè)、成都全網(wǎng)營銷及網(wǎng)站設(shè)計(jì)開發(fā)服務(wù)!

事務(wù)特點(diǎn):ACID

從業(yè)務(wù)角度出發(fā),對數(shù)據(jù)庫的一組操作要求保持4個(gè)特征:

  • Atomicity(原子性):一個(gè)事務(wù)必須被視為一個(gè)不可分割的最小工作單元,整個(gè)事務(wù)中的所有操作要么全部提交成功,要么全部失敗回滾,對于一個(gè)事務(wù)來說,不可能只執(zhí)行其中的一部分操作。

  • Consistency(一致性):數(shù)據(jù)庫總是從一個(gè)一致性狀態(tài)轉(zhuǎn)換到另一個(gè)一致狀態(tài)。下面的銀行列子會說到。

  • Isolation(隔離性):通常來說,一個(gè)事務(wù)所做的修改在最終提交以前,對其他事務(wù)是不可見的。注意這里的“通常來說”,后面的事務(wù)隔離級級別會說到。

  • Durability(持久性):一旦事務(wù)提交,則其所做的修改就會永久保存到數(shù)據(jù)庫中。此時(shí)即使系統(tǒng)崩潰,修改的數(shù)據(jù)也不會丟失。(持久性的安全性與刷新日志級別也存在一定關(guān)系,不同的級別對應(yīng)不同的數(shù)據(jù)安全級別。)

為了更好地理解ACID,以銀行賬戶轉(zhuǎn)賬為例:

START TRANSACTION;SELECT balance FROM checking WHERE customer_id = 10233276;UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;COMMIT;
  • 原子性:要么完全提交(10233276的checking余額減少200,savings 的余額增加200),要么完全回滾(兩個(gè)表的余額都不發(fā)生變化)

  • 一致性:這個(gè)例子的一致性體現(xiàn)在 200元不會因?yàn)閿?shù)據(jù)庫系統(tǒng)運(yùn)行到第3行之后,第4行之前時(shí)崩潰而不翼而飛,因?yàn)槭聞?wù)還沒有提交。

  • 隔離性:允許在一個(gè)事務(wù)中的操作語句會與其他事務(wù)的語句隔離開,比如事務(wù)A運(yùn)行到第3行之后,第4行之前,此時(shí)事務(wù)B去查詢checking余額時(shí),它仍然能夠看到在事務(wù)A中被減去的200元(賬戶錢不變),因?yàn)槭聞?wù)A和B是彼此隔離的。在事務(wù)A提交之前,事務(wù)B觀察不到數(shù)據(jù)的改變。

  • 持久性:這個(gè)很好理解。

  • 事務(wù)的隔離性是通過鎖、MVCC等實(shí)現(xiàn) (MySQL鎖總結(jié))

  • 事務(wù)的原子性、一致性和持久性則是通過事務(wù)日志實(shí)現(xiàn)(見下)

事務(wù)的隔離級別

并發(fā)事務(wù)帶來的問題

  • 更新丟失(Lost Update):當(dāng)兩個(gè)或多個(gè)事務(wù)選擇同一行,然后基于最初選定的值更新該行時(shí),由于每個(gè)事務(wù)都不知道其他事務(wù)的存在,就會發(fā)生丟失更新問題 --最后的更新覆蓋了由其他事務(wù)所做的更新。例如,兩個(gè)編輯人員制作了同一 文檔的電子副本。每個(gè)編輯人員獨(dú)立地更改其副本,然后保存更改后的副本,這樣就覆蓋了原始文檔。 最后保存其更改副本的編輯人員覆蓋另一個(gè)編輯人員所做的更改。如果在一個(gè)編輯人員完成并提交事務(wù)之前,另一個(gè)編輯人員不能訪問同 一文件,則可避免此問題。

  • 臟讀(Dirty Reads):一個(gè)事務(wù)正在對一條記錄做修改,在這個(gè)事務(wù)完成并提交前, 這條記錄的數(shù)據(jù)就處于不一致狀態(tài); 這時(shí), 另一個(gè)事務(wù)也來讀取同一條記錄,如果不加控制,第二個(gè)事務(wù)讀取了這些“臟”數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被形象地叫做”臟讀”。

  • 不可重復(fù)讀(Non-Repeatable Reads):一個(gè)事務(wù)在讀取某些數(shù)據(jù)后的某個(gè)時(shí)間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變、或某些記錄已經(jīng)被刪除了!這種現(xiàn)象就叫做“不可重復(fù)讀” 。

  • 幻讀 (Phantom Reads): 一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀” 。

幻讀和不可重復(fù)讀的區(qū)別:

  • 不可重復(fù)讀的重點(diǎn)是修改:在同一事務(wù)中,同樣的條件,第一次讀的數(shù)據(jù)和第二次讀的數(shù)據(jù)不一樣。(因?yàn)橹虚g有其他事務(wù)提交了修改)

  • 幻讀的重點(diǎn)在于新增或者刪除:在同一事務(wù)中,同樣的條件,,第一次和第二次讀出來的記錄數(shù)不一樣。(因?yàn)橹虚g有其他事務(wù)提交了插入/刪除)

并發(fā)事務(wù)處理帶來的問題的解決辦法:

  • “更新丟失”通常是應(yīng)該完全避免的。但防止更新丟失,并不能單靠數(shù)據(jù)庫事務(wù)控制器來解決,需要應(yīng)用程序?qū)σ碌臄?shù)據(jù)加必要的鎖來解決,因此,防止更新丟失應(yīng)該是應(yīng)用的責(zé)任。

  • “臟讀” 、 “不可重復(fù)讀”和“幻讀” ,其實(shí)都是數(shù)據(jù)庫讀一致性問題,必須由數(shù)據(jù)庫提供一定的事務(wù)隔離機(jī)制來解決:

  • 一種是加鎖:在讀取數(shù)據(jù)前,對其加鎖,阻止其他事務(wù)對數(shù)據(jù)進(jìn)行修改。

  • 另一種是數(shù)據(jù)多版本并發(fā)控制(MultiVersion Concurrency Control,簡稱 MVCC 或 MCC),也稱為多版本數(shù)據(jù)庫:不用加任何鎖, 通過一定機(jī)制生成一個(gè)數(shù)據(jù)請求時(shí)間點(diǎn)的一致性數(shù)據(jù)快照 (Snapshot), 并用這個(gè)快照來提供一定級別 (語句級或事務(wù)級) 的一致性讀取。從用戶的角度來看,好象是數(shù)據(jù)庫可以提供同一數(shù)據(jù)的多個(gè)版本。

SQL標(biāo)準(zhǔn)定義了4類隔離級別,每一種級別都規(guī)定了一個(gè)事務(wù)中所做的修改,哪些在事務(wù)內(nèi)和事務(wù)間是可見的,哪些是不可見的。低級別的隔離級一般支持更高的并發(fā)處理,并擁有更低的系統(tǒng)開銷。

第1級別:Read Uncommitted(讀取未提交內(nèi)容)

  • 所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果

  • 本隔離級別很少用于實(shí)際應(yīng)用,因?yàn)樗男阅芤膊槐绕渌墑e好多少

  • 該級別引發(fā)的問題是——臟讀(Dirty Read):讀取到了未提交的數(shù)據(jù)

第2級別:Read Committed(讀取提交內(nèi)容)

  • 這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認(rèn)隔離級別(但不是MySQL默認(rèn)的)

  • 它滿足了隔離的簡單定義:一個(gè)事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變

  • 這種隔離級別出現(xiàn)的問題是——不可重復(fù)讀(Nonrepeatable Read):不可重復(fù)讀意味著我們在同一個(gè)事務(wù)中執(zhí)行完全相同的select語句時(shí)可能看到不一樣的結(jié)果。導(dǎo)致這種情況的原因可能有:

  • 有一個(gè)交叉的事務(wù)有新的commit,導(dǎo)致了數(shù)據(jù)的改變;

  • 一個(gè)數(shù)據(jù)庫被多個(gè)實(shí)例操作時(shí),同一事務(wù)的其他實(shí)例在該實(shí)例處理其間可能會有新的commit

第3級別:Repeatable Read(可重讀)

  • 這是MySQL的默認(rèn)事務(wù)隔離級別

  • 它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會看到同樣的數(shù)據(jù)行

  • 此級別可能出現(xiàn)的問題——幻讀(Phantom Read):當(dāng)用戶讀取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí),會發(fā)現(xiàn)有新的“幻影” 行

  • InnoDB和Falcon存儲引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決幻讀問題;InnoDB還通過間隙鎖解決幻讀問題

多版本并發(fā)控制 :

Mysql的大多數(shù)事務(wù)型存儲引擎實(shí)現(xiàn)都不是簡單的行級鎖?;谔嵘l(fā)性考慮,一般都同時(shí)實(shí)現(xiàn)了多版本并發(fā)控制(MVCC),包括Oracle、PostgreSQL。不過實(shí)現(xiàn)各不相同。

MVCC的實(shí)現(xiàn)是通過保存數(shù)據(jù)在某一個(gè)時(shí)間點(diǎn)快照來實(shí)現(xiàn)的。也就是說不管實(shí)現(xiàn)時(shí)間多長,每個(gè)事物看到的數(shù)據(jù)都是一致的。

分為樂觀(optimistic)并發(fā)控制和悲觀(pressimistic)并發(fā)控制。

MVCC是如何工作的:

InnoDB的MVCC是通過在每行記錄后面保存兩個(gè)隱藏的列來實(shí)現(xiàn)。這兩個(gè)列一個(gè)保存了行的創(chuàng)建時(shí)間,一個(gè)保存行的過期時(shí)間(刪除時(shí)間)。當(dāng)然存儲的并不是真實(shí)的時(shí)間而是系統(tǒng)版本號(system version number)。每開始一個(gè)新的事務(wù),系統(tǒng)版本號都會自動(dòng)新增。事務(wù)開始時(shí)刻的系統(tǒng)版本號會作為事務(wù)的版本號,用來查詢到每行記錄的版本號進(jìn)行比較。

REPEATABLE READ(可重讀)隔離級別下MVCC如何工作:

  • SELECT

InnoDB會根據(jù)以下條件檢查每一行記錄:

  1. InnoDB只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行,這樣可以確保事務(wù)讀取的行要么是在開始事務(wù)之前已經(jīng)存在要么是事務(wù)自身插入或者修改過的

  2. 行的刪除版本號要么未定義,要么大于當(dāng)前事務(wù)版本號,這樣可以確保事務(wù)讀取到的行在事務(wù)開始之前未被刪除

只有符合上述兩個(gè)條件的才會被查詢出來

  • INSERT

InnoDB為新插入的每一行保存當(dāng)前系統(tǒng)版本號作為行版本號

  • DELETE

InnoDB為刪除的每一行保存當(dāng)前系統(tǒng)版本號作為行刪除標(biāo)識

  • UPDATE

InnoDB為插入的一行新紀(jì)錄保存當(dāng)前系統(tǒng)版本號作為行版本號,同時(shí)保存當(dāng)前系統(tǒng)版本號到原來的行作為刪除標(biāo)識

保存這兩個(gè)版本號,使大多數(shù)操作都不用加鎖。使數(shù)據(jù)操作簡單,性能很好,并且能保證只會讀取到復(fù)合要求的行。不足之處是每行記錄都需要額外的存儲空間,需要做更多的行檢查工作和一些額外的維護(hù)工作。

MVCC只在COMMITTED READ(讀提交)和REPEATABLE READ(可重復(fù)讀)兩種隔離級別下工作。

可以認(rèn)為MVCC是行級鎖一個(gè)變種,但是他很多情況下避免了加鎖操作,開銷更低。雖然不同數(shù)據(jù)庫的實(shí)現(xiàn)機(jī)制有所不同,但大都實(shí)現(xiàn)了非阻塞的讀操作(讀不用加鎖,且能避免出現(xiàn)不可重復(fù)讀和幻讀),寫操作也只鎖定必要的行(寫必須加鎖,否則不同事務(wù)并發(fā)寫會導(dǎo)致數(shù)據(jù)不一致)。

第4級別:Serializable(可串行化)

  • 這是最高的隔離級別

  • 它通過強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖。MySQL鎖總結(jié)

  • 在這個(gè)級別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競爭

隔離級別比較

MySQL數(shù)據(jù)庫事務(wù)的示例分析

各具體數(shù)據(jù)庫并不一定完全實(shí)現(xiàn)了上述 4 個(gè)隔離級別,例如:

  • Oracle 只提供 Read committed 和 Serializable 兩個(gè)標(biāo)準(zhǔn)隔離級別,另外還提供自己定義的 Read only 隔離級別;

  • SQL Server 除支持上述 ISO/ANSI SQL92 定義的 4 個(gè)隔離級別外,還支持一個(gè)叫做“快照”的隔離級別,但嚴(yán)格來說它是一個(gè)用 MVCC 實(shí)現(xiàn)的 Serializable 隔離級別。

  • MySQL 支持全部 4 個(gè)隔離級別,但在具體實(shí)現(xiàn)時(shí),有一些特點(diǎn),比如在一些隔離級別下是采用 MVCC一致性讀,但某些情況下又不是。

  • Mysql可以通過執(zhí)行 set transaction isolation level命令來設(shè)置隔離級別,新的隔離級別會在下一個(gè)事務(wù)開始的時(shí)候生效。 例如:set session transaction isolation level read committed;

事務(wù)日志

事務(wù)日志可以幫助提高事務(wù)效率:

  • 使用事務(wù)日志,存儲引擎在修改表的數(shù)據(jù)時(shí)只需要修改其內(nèi)存拷貝,再把該修改行為記錄到持久在硬盤上的事務(wù)日志中,而不用每次都將修改的數(shù)據(jù)本身持久到磁盤。

  • 事務(wù)日志采用的是追加的方式,因此寫日志的操作是磁盤上一小塊區(qū)域內(nèi)的順序I/O,而不像隨機(jī)I/O需要在磁盤的多個(gè)地方移動(dòng)磁頭,所以采用事務(wù)日志的方式相對來說要快得多。

  • 事務(wù)日志持久以后,內(nèi)存中被修改的數(shù)據(jù)在后臺可以慢慢刷回到磁盤。

  • 如果數(shù)據(jù)的修改已經(jīng)記錄到事務(wù)日志并持久化,但數(shù)據(jù)本身沒有寫回到磁盤,此時(shí)系統(tǒng)崩潰,存儲引擎在重啟時(shí)能夠自動(dòng)恢復(fù)這一部分修改的數(shù)據(jù)。

目前來說,大多數(shù)存儲引擎都是這樣實(shí)現(xiàn)的,我們通常稱之為預(yù)寫式日志(Write-Ahead Logging),修改數(shù)據(jù)需要寫兩次磁盤。

Mysql中的事務(wù)實(shí)現(xiàn)原理

事務(wù)的實(shí)現(xiàn)是基于數(shù)據(jù)庫的存儲引擎。不同的存儲引擎對事務(wù)的支持程度不一樣。mysql中支持事務(wù)的存儲引擎有innoDB和NDB。

innoDB是mysql默認(rèn)的存儲引擎,默認(rèn)的隔離級別是RR(Repeatable Read),并且在RR的隔離級別下更進(jìn)一步,通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control )解決不可重復(fù)讀問題,加上間隙鎖(也就是并發(fā)控制)解決幻讀問題。因此innoDB的RR隔離級別其實(shí)實(shí)現(xiàn)了串行化級別的效果,而且保留了比較好的并發(fā)性能。

事務(wù)的隔離性是通過鎖實(shí)現(xiàn),而事務(wù)的原子性、一致性和持久性則是通過事務(wù)日志實(shí)現(xiàn)。說到事務(wù)日志,不得不說的就是redo和undo。

1.redo log

在innoDB的存儲引擎中,事務(wù)日志通過重做(redo)日志和innoDB存儲引擎的日志緩沖(InnoDB Log Buffer)實(shí)現(xiàn)。事務(wù)開啟時(shí),事務(wù)中的操作,都會先寫入存儲引擎的日志緩沖中,在事務(wù)提交之前,這些緩沖的日志都需要提前刷新到磁盤上持久化,這就是DBA們口中常說的“日志先行”(Write-Ahead Logging)。當(dāng)事務(wù)提交之后,在Buffer Pool中映射的數(shù)據(jù)文件才會慢慢刷新到磁盤。此時(shí)如果數(shù)據(jù)庫崩潰或者宕機(jī),那么當(dāng)系統(tǒng)重啟進(jìn)行恢復(fù)時(shí),就可以根據(jù)redo log中記錄的日志,把數(shù)據(jù)庫恢復(fù)到崩潰前的一個(gè)狀態(tài)。未完成的事務(wù),可以繼續(xù)提交,也可以選擇回滾,這基于恢復(fù)的策略而定。

在系統(tǒng)啟動(dòng)的時(shí)候,就已經(jīng)為redo log分配了一塊連續(xù)的存儲空間,以順序追加的方式記錄Redo Log,通過順序IO來改善性能。所有的事務(wù)共享redo log的存儲空間,它們的Redo Log按語句的執(zhí)行順序,依次交替的記錄在一起。如下一個(gè)簡單示例:

記錄1:<trx1, insert…>

記錄2:<trx2, delete…>

記錄3:<trx3, update…>

記錄4:<trx1, update…>

記錄5:<trx3, insert…>

2.undo log

undo log主要為事務(wù)的回滾服務(wù)。在事務(wù)執(zhí)行的過程中,除了記錄redo log,還會記錄一定量的undo log。undo log記錄了數(shù)據(jù)在每個(gè)操作前的狀態(tài),如果事務(wù)執(zhí)行過程中需要回滾,就可以根據(jù)undo log進(jìn)行回滾操作。單個(gè)事務(wù)的回滾,只會回滾當(dāng)前事務(wù)做的操作,并不會影響到其他的事務(wù)做的操作。

以下是undo+redo事務(wù)的簡化過程

假設(shè)有2個(gè)數(shù)值,分別為A和B,值為1,2

1. start transaction;

2. 記錄 A=1 到undo log;

3. update A = 3;

4. 記錄 A=3 到redo log;

5. 記錄 B=2 到undo log;

6. update B = 4;

7. 記錄B = 4 到redo log;

8. 將redo log刷新到磁盤

9. commit

在1-8的任意一步系統(tǒng)宕機(jī),事務(wù)未提交,該事務(wù)就不會對磁盤上的數(shù)據(jù)做任何影響。如果在8-9之間宕機(jī),恢復(fù)之后可以選擇回滾,也可以選擇繼續(xù)完成事務(wù)提交,因?yàn)榇藭r(shí)redo log已經(jīng)持久化。若在9之后系統(tǒng)宕機(jī),內(nèi)存映射中變更的數(shù)據(jù)還來不及刷回磁盤,那么系統(tǒng)恢復(fù)之后,可以根據(jù)redo log把數(shù)據(jù)刷回磁盤。

所以,redo log其實(shí)保障的是事務(wù)的持久性和一致性,而undo log則保障了事務(wù)的原子性。

Mysql中的事務(wù)使用

MySQL的服務(wù)層不管理事務(wù),而是由下層的存儲引擎實(shí)現(xiàn)。比如InnoDB。

MySQL支持本地事務(wù)的語句:

START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1}
  • START TRANSACTION 或 BEGIN 語句:開始一項(xiàng)新的事務(wù)。

  • COMMIT 和 ROLLBACK:用來提交或者回滾事務(wù)。

  • CHAIN 和 RELEASE 子句:分別用來定義在事務(wù)提交或者回滾之后的操作,CHAIN 會立即啟動(dòng)一個(gè)新事物,并且和剛才的事務(wù)具有相同的隔離級別,RELEASE 則會斷開和客戶端的連接。

  • SET AUTOCOMMIT 可以修改當(dāng)前連接的提交方式, 如果設(shè)置了 SET AUTOCOMMIT=0,則設(shè)置之后的所有事務(wù)都需要通過明確的命令進(jìn)行提交或者回滾

事務(wù)使用注意點(diǎn):

  • 如果在鎖表期間,用 start transaction 命令開始一個(gè)新事務(wù),會造成一個(gè)隱含的 unlock
    tables 被執(zhí)行。

  • 在同一個(gè)事務(wù)中,最好不使用不同存儲引擎的表,否則 ROLLBACK 時(shí)需要對非事
    務(wù)類型的表進(jìn)行特別的處理,因?yàn)?COMMIT、ROLLBACK 只能對事務(wù)類型的表進(jìn)行提交和回滾。

  • 和 Oracle 的事務(wù)管理相同,所有的 DDL 語句是不能回滾的,并且部分的 DDL 語句會造成隱式的提交。

  • 在事務(wù)中可以通過定義 SAVEPOINT(例如:mysql> savepoint test; 定義 savepoint,名稱為 test),指定回滾事務(wù)的一個(gè)部分,但是不能指定提交事務(wù)的一個(gè)部分。對于復(fù)雜的應(yīng)用,可以定義多個(gè)不同的 SAVEPOINT,滿足不同的條件時(shí),回滾
    不同的 SAVEPOINT。需要注意的是,如果定義了相同名字的 SAVEPOINT,則后面定義的SAVEPOINT 會覆蓋之前的定義。對于不再需要使用的 SAVEPOINT,可以通過 RELEASE SAVEPOINT 命令刪除 SAVEPOINT, 刪除后的 SAVEPOINT, 不能再執(zhí)行 ROLLBACK TO SAVEPOINT命令。

自動(dòng)提交(autocommit):
Mysql默認(rèn)采用自動(dòng)提交模式,可以通過設(shè)置autocommit變量來啟用或禁用自動(dòng)提交模式

  • 隱式鎖定

InnoDB在事務(wù)執(zhí)行過程中,使用兩階段鎖協(xié)議:

隨時(shí)都可以執(zhí)行鎖定,InnoDB會根據(jù)隔離級別在需要的時(shí)候自動(dòng)加鎖;

鎖只有在執(zhí)行commit或者rollback的時(shí)候才會釋放,并且所有的鎖都是在同一時(shí)刻被釋放。

  • 顯式鎖定

InnoDB也支持通過特定的語句進(jìn)行顯示鎖定(存儲引擎層):

select ... lock in share mode //共享鎖 select ... for update //排他鎖

MySQL Server層的顯示鎖定:

lock table和unlock table

(更多閱讀:MySQL鎖總結(jié))

MySQL對分布式事務(wù)的支持

分布式事務(wù)的實(shí)現(xiàn)方式有很多,既可以采用innoDB提供的原生的事務(wù)支持,也可以采用消息隊(duì)列來實(shí)現(xiàn)分布式事務(wù)的最終一致性。這里我們主要聊一下innoDB對分布式事務(wù)的支持。

MySQL 從 5.0.3 開始支持分布式事務(wù),當(dāng)前分布式事務(wù)只支持 InnoDB 存儲引擎。一個(gè)分布式事務(wù)會涉及多個(gè)行動(dòng),這些行動(dòng)本身是事務(wù)性的。所有行動(dòng)都必須一起成功完成,或者一起被回滾。

MySQL數(shù)據(jù)庫事務(wù)的示例分析

如圖,mysql的分布式事務(wù)模型。模型中分三塊:應(yīng)用程序(AP)、資源管理器(RM)、事務(wù)管理器(TM):

  • 應(yīng)用程序:定義了事務(wù)的邊界,指定需要做哪些事務(wù);

  • 資源管理器:提供了訪問事務(wù)的方法,通常一個(gè)數(shù)據(jù)庫就是一個(gè)資源管理器;

  • 事務(wù)管理器:協(xié)調(diào)參與了全局事務(wù)中的各個(gè)事務(wù)。

分布式事務(wù)采用兩段式提交(two-phase commit)的方式:

  • 第一階段所有的事務(wù)節(jié)點(diǎn)開始準(zhǔn)備,告訴事務(wù)管理器ready。

  • 第二階段事務(wù)管理器告訴每個(gè)節(jié)點(diǎn)是commit還是rollback。如果有一個(gè)節(jié)點(diǎn)失敗,就需要全局的節(jié)點(diǎn)全部rollback,以此保障事務(wù)的原子性。

分布式事務(wù)(XA 事務(wù))的 SQL 語法主要包括:

XA {START|BEGIN} xid [JOIN|RESUME]

雖然 MySQL 支持分布式事務(wù),但是在測試過程中,還是發(fā)現(xiàn)存在一些問題:
如果分支事務(wù)在達(dá)到 prepare 狀態(tài)時(shí),數(shù)據(jù)庫異常重新啟動(dòng),服務(wù)器重新啟動(dòng)以后,可以繼續(xù)對分支事務(wù)進(jìn)行提交或者回滾得操作,但是提交的事務(wù)沒有寫 binlog,存在一定的隱患,可能導(dǎo)致使用 binlog 恢復(fù)丟失部分?jǐn)?shù)據(jù)。如果存在復(fù)制的數(shù)據(jù)庫,則有可能導(dǎo)致主從數(shù)據(jù)庫的數(shù)據(jù)不一致。

如果分支事務(wù)在執(zhí)行到 prepare 狀態(tài)時(shí),數(shù)據(jù)庫異常,且不能再正常啟動(dòng),需要使用備份和 binlog 來恢復(fù)數(shù)據(jù),那么那些在 prepare 狀態(tài)的分支事務(wù)因?yàn)椴]有記錄到 binlog,所以不能通過 binlog 進(jìn)行恢復(fù),在數(shù)據(jù)庫恢復(fù)后,將丟失這部分的數(shù)據(jù)。

如果分支事務(wù)的客戶端連接異常中止,那么數(shù)據(jù)庫會自動(dòng)回滾未完成的分支事務(wù),如果此時(shí)分支事務(wù)已經(jīng)執(zhí)行到 prepare 狀態(tài), 那么這個(gè)分布式事務(wù)的其他分支可能已經(jīng)成功提交,如果這個(gè)分支回滾,可能導(dǎo)致分布式事務(wù)的不完整,丟失部分分支事務(wù)的內(nèi)容。
總之, MySQL 的分布式事務(wù)還存在比較嚴(yán)重的缺陷, 在數(shù)據(jù)庫或者應(yīng)用異常的情況下,
可能會導(dǎo)致分布式事務(wù)的不完整。如果應(yīng)用對于數(shù)據(jù)的完整性要求不是很高,則可以考慮使
用。如果應(yīng)用對事務(wù)的完整性有比較高的要求,那么對于當(dāng)前的版本,則不推薦使用分布式
事務(wù)。                            

以上是“MySQL數(shù)據(jù)庫事務(wù)的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

網(wǎng)站欄目:MySQL數(shù)據(jù)庫事務(wù)的示例分析
分享網(wǎng)址:http://muchs.cn/article38/iepgsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站策劃、移動(dòng)網(wǎng)站建設(shè)、企業(yè)建站、域名注冊、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)