一、概念
什么是事務(wù)
數(shù)據(jù)庫(kù)事務(wù)(簡(jiǎn)稱:事務(wù))是數(shù)據(jù)庫(kù)管理系統(tǒng)執(zhí)行過程中的一個(gè)邏輯單位候生,由一個(gè)有限的數(shù)據(jù)庫(kù)操作序列構(gòu)成丹擎。
當(dāng)事務(wù)被提交給了DBMS(數(shù)據(jù)庫(kù)管理系統(tǒng))姚垃,則DBMS需要確保該事務(wù)中的所有操作都成功完成且其結(jié)果被永久保存在數(shù)據(jù)庫(kù)中侮邀,如果事務(wù)中有的操作沒有成功完成坏怪,則事務(wù)中的所有操作都需要被回滾,回到事務(wù)執(zhí)行前的狀態(tài);同時(shí)绊茧,該事務(wù)對(duì)數(shù)據(jù)庫(kù)或者其他事務(wù)的執(zhí)行無(wú)影響铝宵,所有的事務(wù)都好像在獨(dú)立的運(yùn)行。為什么需要事務(wù)
a.為數(shù)據(jù)庫(kù)操作序列提供了一個(gè)從失敗中恢復(fù)到正常狀態(tài)的方法按傅,同時(shí)提供了數(shù)據(jù)庫(kù)即使在異常狀態(tài)下仍能保持一致性的方法捉超。
b.當(dāng)多個(gè)應(yīng)用程序在并發(fā)訪問數(shù)據(jù)庫(kù)時(shí),可以在這些應(yīng)用程序之間提供一個(gè)隔離方法唯绍,以防止彼此的操作互相干擾。事務(wù)的4個(gè)特性--ACID
原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行枝誊,包含在其中的對(duì)數(shù)據(jù)庫(kù)的操作要么全部被執(zhí)行况芒,要么都不執(zhí)行。
一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫(kù)的狀態(tài)從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài)叶撒。一致狀態(tài)的含義是數(shù)據(jù)庫(kù)中的數(shù)據(jù)應(yīng)滿足完整性約束绝骚。
隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行祠够。
持久性(Durability):已被提交的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改應(yīng)該永久保存在數(shù)據(jù)庫(kù)中压汪。
二、MySQL事務(wù)
2.1 事務(wù)類型
該部分引用自說說MySQL中的事務(wù)
-
扁平事務(wù)
扁平事務(wù)是最簡(jiǎn)單的一種古瓤,也是實(shí)際開發(fā)中使用的最多的一種事務(wù)止剖。在這種事務(wù)中,所有操作都處于同一層次落君,最常見的方式如下:
BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
COMMIT WORK
或者是這種:
BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
(Error Occured)
ROLLBACK WORK
扁平事務(wù)的主要缺點(diǎn)是不能提交或回滾事務(wù)的某一部分穿香,或者分幾個(gè)獨(dú)立的步驟去提交。
帶有保存點(diǎn)的扁平事務(wù)
這種事務(wù)除了支持扁平事務(wù)支持的操作外绎速,允許在事務(wù)執(zhí)行過程中回滾到同一事務(wù)中較早的一個(gè)狀態(tài)皮获,這是因?yàn)榭赡苣承┦聞?wù)在執(zhí)行過程中出現(xiàn)的錯(cuò)誤并不會(huì)對(duì)所有的操作都無(wú)效,放棄整個(gè)事務(wù)不合乎要求纹冤,開銷也太大洒宝。保存點(diǎn)用來(lái)通知系統(tǒng)應(yīng)該記住事務(wù)當(dāng)前的狀態(tài),以便以后發(fā)生錯(cuò)誤時(shí)萌京,事務(wù)能回到該狀態(tài)雁歌。鏈?zhǔn)聞?wù)
鏈?zhǔn)聞?wù),就是指回滾時(shí)枫夺,只能恢復(fù)到最近一個(gè)保存點(diǎn)将宪;而帶有保存點(diǎn)的扁平事務(wù)則可以回滾到任意正確的保存點(diǎn)。嵌套事務(wù)
在事務(wù)中再嵌套事務(wù),位于根節(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ǎng)絡(luò)中的不同節(jié)點(diǎn)
2.2 使用事務(wù)
-
事務(wù)設(shè)置
在MySQL命令行的默認(rèn)設(shè)置下型宝,事務(wù)都是自動(dòng)提交的,即執(zhí)行SQL語(yǔ)句后就會(huì)馬上執(zhí)行COMMIT操作絮爷。
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set
因此要顯示地開啟一個(gè)事務(wù)須使用命令BEGIN
或START TRANSACTION
趴酣,或者執(zhí)行命令SET AUTOCOMMIT=0
,用來(lái)禁止使用當(dāng)前會(huì)話的自動(dòng)提交坑夯。
mysql> SET AUTOCOMMIT=0;
Query OK, 0 rows affected
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set
另外岖寞,對(duì)于常見的兩種存儲(chǔ)引擎,InnoDB支持事務(wù)柜蜈,MyISAM不支持仗谆。
事務(wù)控制語(yǔ)句
BEGIN
或START TRANSACTION
:顯示地開啟一個(gè)事務(wù);COMMIT
或COMMIT WORK
:提交事務(wù)跨释,并使已對(duì)數(shù)據(jù)庫(kù)進(jìn)行的所有修改成為永久性的胸私;ROLLBACK
或ROLLBACK WORK
:回滾,結(jié)束用戶的事務(wù)鳖谈,并撤銷正在進(jìn)行的所有未提交的修改岁疼;SAVEPOINT identifier
:在事務(wù)中創(chuàng)建一個(gè)保存點(diǎn),一個(gè)事務(wù)中可以有多個(gè)保存點(diǎn)缆娃;RELEASE SAVEPOINT identifier
:刪除一個(gè)事務(wù)的保存點(diǎn)捷绒,當(dāng)沒有指定的保存點(diǎn)時(shí),執(zhí)行該語(yǔ)句會(huì)拋出一個(gè)異常贯要;ROLLBACK TO identifier
:把事務(wù)回滾到標(biāo)記點(diǎn)暖侨;SET TRANSACTION
:設(shè)置事務(wù)的隔離級(jí)別。InnoDB存儲(chǔ)引擎提供事務(wù)的隔離級(jí)別有READ UNCOMMITTED
崇渗、READ COMMITTED
字逗、REPEATABLE READ
和SERIALIZABLE
京郑。
2.3 事務(wù)隔離級(jí)別
先看一個(gè)表格總結(jié):
隔離級(jí)別 | 臟讀(Dirty Read) | 不可重復(fù)讀(NonRepeatable Read) | 幻讀(Phantom Read) |
---|---|---|---|
未提交讀:Read uncommitted | yes | yes | yes |
已提交讀:Read committed | no | yes | yes |
可重復(fù)讀:Repeatable read | no | no | yes |
可串行化:Serializable | no | no | no |
注:yes只是指有可能,并不一定會(huì)發(fā)生葫掉;no是指絕對(duì)不會(huì)發(fā)生些举。
再看具體釋義:
未提交讀:Read uncommitted
在該隔離級(jí)別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果俭厚。
本隔離級(jí)別很少用于實(shí)際應(yīng)用户魏,因?yàn)樗男阅芤膊槐绕渌?jí)別好多少。讀取未提交的數(shù)據(jù)挪挤,也被稱之為臟讀(Dirty Read)叼丑。已提交讀:Read committed
這是大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)的默認(rèn)隔離級(jí)別(但不是MySQL默認(rèn)的)。它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變扛门。這種隔離級(jí)別也支持所謂的不可重復(fù)讀(Nonrepeatable Read)鸠信,因?yàn)橥皇聞?wù)的其他實(shí)例在該實(shí)例處理期間可能會(huì)有新的commit,所以同一select可能返回不同結(jié)果尖飞。可重復(fù)讀:Repeatable read
這是MySQL的默認(rèn)事務(wù)隔離級(jí)別症副,它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行政基。不過理論上,這會(huì)導(dǎo)致另一個(gè)棘手的問題:幻讀 (Phantom Read)闹啦。簡(jiǎn)單的說沮明,幻讀指當(dāng)用戶讀取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行窍奋,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí)荐健,會(huì)發(fā)現(xiàn)有新的“幻影” 行。InnoDB和Falcon存儲(chǔ)引擎通過多版本并發(fā)控制(MVCC琳袄,Multiversion Concurrency Control)機(jī)制解決了該問題江场。可串行化:Serializable
這是最高的隔離級(jí)別,它通過強(qiáng)制事務(wù)排序窖逗,使之不可能相互沖突址否,從而解決幻讀問題。簡(jiǎn)言之碎紊,它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖佑附。在這個(gè)級(jí)別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競(jìng)爭(zhēng)仗考。
一些概念補(bǔ)充
-
臟讀(Drity Read)
某個(gè)事務(wù)已更新一份數(shù)據(jù)(但還未提交)音同,另一個(gè)事務(wù)在此時(shí)讀取了同一份數(shù)據(jù),由于某些原因秃嗜,前一個(gè)RollBack了操作权均,則后一個(gè)事務(wù)所讀取的數(shù)據(jù)就會(huì)是不正確的顿膨,臟的。 -
不可重復(fù)讀(Non-repeatable read)
在一個(gè)事務(wù)的兩次查詢之中數(shù)據(jù)不一致叽赊,即同一事務(wù)中恋沃,同樣的條件 , 讀取過的數(shù)據(jù) , 再次讀取出來(lái)發(fā)現(xiàn)值不一樣了。這可能是兩次查詢過程中間插入了一個(gè)事務(wù)更新的原有的數(shù)據(jù)蛇尚。 -
幻讀(Phantom Read)
在一個(gè)事務(wù)的兩次查詢中數(shù)據(jù)不一致芽唇。重點(diǎn)在于新增或者刪除:同樣的條件 , 第 1 次和第 2 次讀出來(lái)的記錄數(shù)不一樣。例如有一個(gè)事務(wù)查詢了幾列(Row)數(shù)據(jù)取劫,而另一個(gè)事務(wù)卻在此時(shí)插入了新的幾列數(shù)據(jù)匆笤,先前的事務(wù)在接下來(lái)的查詢中,就會(huì)發(fā)現(xiàn)有幾列數(shù)據(jù)是它先前所沒有的谱邪。
更新
20180116--細(xì)化幻讀和不可重復(fù)讀的概念區(qū)分