MySQL事務(wù),這篇文章就夠了
0 什么是事務(wù)
事務(wù)(Transaction) 是并發(fā)控制的基本單位。所謂的事務(wù),它是一個(gè)操作序列,這些操作要么都 執(zhí)行,要么都不執(zhí)行,它是一個(gè)不可分割的工作單位。事務(wù)是數(shù)據(jù)庫(kù)維護(hù)數(shù)據(jù)一致性的單位,在每 個(gè)事務(wù)結(jié)束時(shí),都能保持?jǐn)?shù)據(jù)一致性。
同時(shí),事務(wù)有著嚴(yán)格的地定義,必須滿足四個(gè)特性,也就是我們一直說(shuō)的ACID,但是,并不是說(shuō)各種數(shù)據(jù)庫(kù)就一定會(huì)滿足四個(gè)特性,對(duì)于不同的數(shù)據(jù)庫(kù)的實(shí)現(xiàn)來(lái)說(shuō),在不同程度上是不一定完全滿足要求的,比如,Oracle數(shù)據(jù)庫(kù)來(lái)說(shuō),默認(rèn)的事務(wù)隔離級(jí)別是READ COMMITTED,是不滿足隔離性的要求的。
下面我們趁熱打鐵,介紹一下事務(wù)的必知必會(huì)的四大特性,這幾個(gè)特性也是在面試中,面試官面試MySQL的相關(guān)知識(shí)的時(shí)候,問(wèn)的比較多的問(wèn)題,所以,這幾個(gè)特性務(wù)必需要理解并且透徹的記在心里,開(kāi)個(gè)玩笑,被火車(chē)撞了,也不應(yīng)該忘記這四個(gè)特性!
1 事務(wù)的四大特性
事務(wù)的四大特性簡(jiǎn)稱為:ACID,分別是原子性、一致性、隔離性和持久性。
下面我們一一來(lái)介紹一下。
- 原子性(Atomicity)
原子性指的是整個(gè)數(shù)據(jù)庫(kù)的事務(wù)是一個(gè)不可分割的工作單位,每一個(gè)都應(yīng)該是一個(gè)原子操作。
當(dāng)我們執(zhí)行一個(gè)事務(wù)的時(shí)候,如果一系列的操作中,有一個(gè)操作失敗了,那么,需要將這一個(gè)事務(wù)中的所有操作恢復(fù)到執(zhí)行事務(wù)之前的狀態(tài),這就是事務(wù)的原子性。
下面舉個(gè)簡(jiǎn)單的例子。
- i++;
上面這個(gè)最簡(jiǎn)單不過(guò)的代碼經(jīng)常也會(huì)被問(wèn)到,這是一個(gè)原子操作嗎?那肯定不是,如果我們把這個(gè)代碼放到一個(gè)事務(wù)中來(lái)說(shuō),當(dāng)i+1出現(xiàn)問(wèn)題的時(shí)候,回滾的就是整個(gè)代碼i++(i = i + 1)了,所以回滾之后,i的值也是不會(huì)改變的。
以上就是原子性的概念。
- 一致性(consistency)
一致性是指事務(wù)將數(shù)據(jù)庫(kù)從一種狀態(tài)轉(zhuǎn)變?yōu)橄乱环N一致性的狀態(tài),也就是說(shuō)在事務(wù)執(zhí)行前后,這兩種狀態(tài)應(yīng)該是一樣的,也就是數(shù)據(jù)庫(kù)的完整性約束不會(huì)被破壞。
另外,需要注意的是一致性是不關(guān)注中間狀態(tài)的,比如銀行轉(zhuǎn)賬的過(guò)程,你轉(zhuǎn)賬給別人,至于中間的狀態(tài),你少了500 ,他多了500,這些中間狀態(tài)不關(guān)注,如果分多次轉(zhuǎn)賬中間狀態(tài)也是不可見(jiàn)的,只有最后的成功或者失敗的狀態(tài)是可見(jiàn)的。
如果到分布式的一致性問(wèn)題,又可以分為強(qiáng)一致性、弱一致性和最終一致性,關(guān)于這些概念,可以自己查查,還是很有意思的。
- 隔離性(isolation)
事務(wù)我們是可以開(kāi)啟很多的,MySQL數(shù)據(jù)庫(kù)中可以同時(shí)啟動(dòng)很多的事務(wù),但是,事務(wù)和事務(wù)之間他們是相互分離的,也就是互不影響的,這就是事務(wù)的隔離性。
- 持久性(durability)
事務(wù)的持久性是指事務(wù)一旦提交,就是永久的了,就是發(fā)生問(wèn)題,數(shù)據(jù)庫(kù)也是可以恢復(fù)的。因此,持久性保證事務(wù)的高可靠性。
2 事務(wù)的分類(lèi)
事務(wù)可以分為很多中類(lèi)型,一般分為:扁平事務(wù)、帶有保存點(diǎn)的扁平事務(wù)、鏈?zhǔn)聞?wù)、嵌套事務(wù)、分布式事務(wù)。
扁平事務(wù)
扁平事務(wù)是最簡(jiǎn)單的一種,在實(shí)際開(kāi)發(fā)中也是使用的最多的一種事務(wù)。在這種事務(wù)中,所有操作都處于同一層次,最常見(jiàn)的方式如下:
- BEGIN WORK
- Operation 1
- Operation 2
- Operation 3
- ...
- Operation N
- COMMIT WORK
舉個(gè)例子
- begin work;
- select * from user;
- update user set name = 'sihai' where id = 1;
- commit work;
扁平事務(wù)的主要缺點(diǎn)是不能提交或回滾事務(wù)的某一部分,或者分幾個(gè)獨(dú)立的步驟去提交。
帶有保存點(diǎn)的扁平事務(wù)
這種事務(wù)除了支持扁平事務(wù)支持的操作外,這種事務(wù)跟扁平事務(wù)最大的區(qū)別就是允許在事務(wù)執(zhí)行過(guò)程中回滾到同一事務(wù)中較早的一個(gè)狀態(tài),這是因?yàn)榭赡苣承┦聞?wù)在執(zhí)行過(guò)程中出現(xiàn)的錯(cuò)誤并不會(huì)對(duì)所有的操作都無(wú)效,放棄整個(gè)事務(wù)不合乎要求,開(kāi)銷(xiāo)也太大。保存點(diǎn)用來(lái)通知系統(tǒng)應(yīng)該記住事務(wù)當(dāng)前的狀態(tài),以便以后發(fā)生錯(cuò)誤時(shí),事務(wù)能回到該狀態(tài)。
舉個(gè)例子
- begin work;
- select * from user;
- savepoint t1;
- update user set name = 'sihai' where id = 1;
- savepoint t2;
- commit work;
通過(guò)上面的方式我們就建立了兩個(gè)保存點(diǎn)t1、t2,通過(guò)ROLLBACK TO SAVEPOINT t1,我們就可以返回到保存點(diǎn)t1。
鏈?zhǔn)聞?wù)
鏈?zhǔn)聞?wù):在提交一個(gè)事務(wù)時(shí),釋放不需要的數(shù)據(jù)對(duì)象,將必要的處理上下文隱式的傳給下一個(gè)要開(kāi)始的事務(wù)。需要注意,提交事務(wù)操作和下一個(gè)事務(wù)操作將合并為一個(gè)原子操作,就是下一個(gè)事務(wù)可以看到上一個(gè)事務(wù)的結(jié)果。
鏈?zhǔn)聞?wù),就是指回滾時(shí),只能恢復(fù)到最近一個(gè)保存點(diǎn);而帶有保存點(diǎn)的扁平事務(wù)則可以回滾到任意正確的保存點(diǎn)。
舉個(gè)例子
- begin work;
- select * from user;
- savepoint t1;
- update user set name = 'sihai' where id = 1;
- savepoint t2;
- commit work;
還是這個(gè)例子,但是對(duì)于鏈?zhǔn)聞?wù)來(lái)說(shuō),是不能直接rollback到保存點(diǎn)t1的,最能恢復(fù)到最近的一個(gè)保存點(diǎn)t2;另外我們需要注意,鏈?zhǔn)聞?wù)在執(zhí)行commit后就會(huì)釋放當(dāng)前事務(wù)所持有的所有鎖,而帶有保存點(diǎn)的扁平事務(wù)不會(huì)影響所持有的鎖。
嵌套事務(wù)
在事務(wù)中再嵌套事務(wù),這種結(jié)構(gòu)有點(diǎn)像一顆橫著的樹(shù)的結(jié)構(gòu),位于根節(jié)點(diǎn)的事務(wù)稱為頂層事務(wù)。事務(wù)的前驅(qū)稱為父事務(wù),其它事務(wù)稱為子事務(wù)。事務(wù)的前驅(qū)稱為父事務(wù),事務(wù)的下一層稱為子事務(wù)。
子事務(wù)既可以提交也可以回滾,但是它的提交操作并不馬上生效,除非由其父事務(wù)提交。因此就可以確定,任何子事務(wù)都在頂層事務(wù)提交后才真正的被提交了。同理,任意一個(gè)事務(wù)的回滾都會(huì)引起它的所有子事務(wù)一同回滾。
- BEGIN WORK
- SubTransaction1:
- BEGIN WORK
- SubOperationX
- COMMIT WORK
- SubTransaction2:
- BEGIN WORK
- SubOperationY
- COMMIT WORK
- ...
- SubTransactionN:
- BEGIN WORK
- SubOperationN
- COMMIT WORK
- COMMIT WORK
分布式事務(wù)
分布式事務(wù)通常是指在一個(gè)分布式環(huán)境下運(yùn)行的扁平事務(wù),因此需要根據(jù)數(shù)據(jù)所在位置訪問(wèn)網(wǎng)絡(luò)中的不同節(jié)點(diǎn)。
在不同的物理地址,通過(guò)網(wǎng)絡(luò)訪問(wèn),執(zhí)行不同的事務(wù),這就是分布式事務(wù)。
3 事務(wù)的使用
首先這一部分我們還是先介紹一下這些事務(wù)的語(yǔ)句,也不是很多,使用也不復(fù)雜,下面用一個(gè)表格做一個(gè)整理。
注意:COMMIT和COMMIT WORK語(yǔ)句不同之處在于COMMIT WORK用來(lái)控制事務(wù)結(jié)束后的行為是CHAIN還是RELEASE,如果是CHAIN,那么事務(wù)就是鏈?zhǔn)聞?wù)。
用戶可以通過(guò)參數(shù)completion_type控制,如下:
- completion_type = 1 實(shí)例
執(zhí)行下面的操作;
- SET @@completion_type = 1;
- BEGIN WORK;
- INSERT INTO lock_test SELECT 10;
- COMMIT WORK;
接著我們?cè)賵?zhí)行下面的操作;
- INSERT INTO lock_test SELECT 115;
- ROLLBACK;
- SELECT * FROM lock_test;
我們先插入一條數(shù)據(jù)115,然后再回滾,我們知道如果不是在一個(gè)事務(wù)的時(shí)候,115應(yīng)該是會(huì)插入成功的,就算我們回滾了,但是,這里我們回滾之后,查詢結(jié)果如下:
這個(gè)時(shí)候并沒(méi)有115這條記錄,也就是回滾生效了,說(shuō)明在COMMIT WORK之后,又是一個(gè)新的事務(wù),所以才會(huì)出現(xiàn)這樣的結(jié)果。
- completion_type = 2 實(shí)例
我們先進(jìn)行下面的操作;
- SET @@completion_type = 2;
- BEGIN WORK;
- INSERT INTO lock_test SELECT 5;
- COMMIT WORK;
上面我們已經(jīng)提交事務(wù)了,當(dāng)我們使用下面的語(yǔ)句查詢lock_test的數(shù)據(jù)的時(shí)候,就會(huì)出現(xiàn)斷開(kāi)連接。
- SELECT * FROM lock_test;
4 事務(wù)的隔離級(jí)別
事務(wù)的隔離級(jí)別有四種分別是:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
對(duì)于這幾種隔離級(jí)別會(huì)帶來(lái)的問(wèn)題及總結(jié),可以查看這篇文章:MySQL的又一神器-鎖,MySQL面試必備
5 總結(jié)
這篇文章從下面幾個(gè)內(nèi)容介紹了一下MySQL數(shù)據(jù)庫(kù)事務(wù)的內(nèi)容,更詳細(xì)的其他內(nèi)容在后面的文章中再講解。
- 概念
- 事務(wù)類(lèi)型
- 事務(wù)使用
- 事務(wù)的隔離級(jí)別
文章有不當(dāng)之處,歡迎指正,如果喜歡微信閱讀,你也可以關(guān)注我的微信公眾號(hào):好好學(xué)java,獲取優(yōu)質(zhì)學(xué)習(xí)資源。

































