MySQL系列(三)----事務(wù)和并發(fā)一致性問(wèn)題

什么是事務(wù)

事務(wù)指的是滿(mǎn)足 ACID 特性的一組操作,可以通過(guò) Commit 提交一個(gè)事務(wù),也可以使用 Rollback 進(jìn)行回滾。

事務(wù)是并發(fā)控制的單位,一系列操作組成的工作單元,該工作單元內(nèi)的操作是不可分割的,也就是事務(wù)具有原子性,一個(gè)事務(wù)中的一系列的操作要么全部成功,要么一個(gè)都不做,所有操作必須成功完成,否則在每個(gè)操作中所作的所有更改都會(huì)被撤消。?

事務(wù)的結(jié)束有兩種,當(dāng)事務(wù)中的所有步驟全部成功執(zhí)行時(shí),事務(wù)提交。如果其中一個(gè)步驟失敗,將發(fā)生回滾操作,撤消撤消之前到事務(wù)開(kāi)始時(shí)的所以操作。?

事務(wù)的ACID

1. 原子性(Atomicity)

事務(wù)被視為不可分割的最小單元,事務(wù)的所有操作要么全部提交成功,要么全部失敗回滾。

回滾可以用回滾日志來(lái)實(shí)現(xiàn),回滾日志記錄著事務(wù)所執(zhí)行的修改操作,在回滾時(shí)反向執(zhí)行這些修改操作即可。

2. 一致性(Consistency)

數(shù)據(jù)庫(kù)在事務(wù)執(zhí)行前后都保持一致性狀態(tài)。在一致性狀態(tài)下,所有事務(wù)對(duì)一個(gè)數(shù)據(jù)的讀取結(jié)果都是相同的。

3. 隔離性(Isolation)

一個(gè)事務(wù)所做的修改在最終提交以前,對(duì)其它事務(wù)是不可見(jiàn)的。

4. 持久性(Durability)

一旦事務(wù)提交,則其所做的修改將會(huì)永遠(yuǎn)保存到數(shù)據(jù)庫(kù)中。即使系統(tǒng)發(fā)生崩潰,事務(wù)執(zhí)行的結(jié)果也不能丟失。

使用重做日志來(lái)保證持久性。

事務(wù)的 ACID 特性概念簡(jiǎn)單,但不是很好理解,主要是因?yàn)檫@幾個(gè)特性不是一種平級(jí)關(guān)系:

1、只有滿(mǎn)足一致性,事務(wù)的執(zhí)行結(jié)果才是正確的。

2、在無(wú)并發(fā)的情況下,事務(wù)串行執(zhí)行,隔離性一定能夠滿(mǎn)足。此時(shí)只要能滿(mǎn)足原子性,就一定能滿(mǎn)足一致性。

3、在并發(fā)的情況下,多個(gè)事務(wù)并行執(zhí)行,事務(wù)不僅要滿(mǎn)足原子性,還需要滿(mǎn)足隔離性,才能滿(mǎn)足一致性。

4、事務(wù)滿(mǎn)足持久化是為了能應(yīng)對(duì)數(shù)據(jù)庫(kù)崩潰的情況。

并發(fā)一致性問(wèn)題

在并發(fā)環(huán)境下,事務(wù)的隔離性很難保證,因此會(huì)出現(xiàn)很多并發(fā)一致性問(wèn)題。

T1是指事務(wù)1,T2是指事務(wù)2

丟失修改:兩個(gè)事務(wù)同時(shí)操作相同數(shù)據(jù),后提交的事務(wù)會(huì)覆蓋先提交的事務(wù)處理結(jié)果,通過(guò)樂(lè)觀鎖就可以解決,悲觀鎖也可以。

例如:T 1 和 T 2 兩個(gè)事務(wù)都對(duì)一個(gè)數(shù)據(jù)進(jìn)行修改,T 1 先修改,T 2 隨后修改,T 2 的修改覆蓋了 T 1 的修改。

讀臟數(shù)據(jù):事務(wù)A讀取到了事務(wù)B已經(jīng)修改但尚未提交的數(shù)據(jù),如果事務(wù)B回滾,A讀取的數(shù)據(jù)無(wú)效,不符合一致性

例如:T 1 修改一個(gè)數(shù)據(jù),T 2 隨后讀取這個(gè)數(shù)據(jù)。如果 T 1 撤銷(xiāo)了這次修改,那么 T 2 讀取的數(shù)據(jù)是臟數(shù)據(jù)。

不可重復(fù)讀:事務(wù)A讀取到了事務(wù)B已經(jīng)提交的修改數(shù)據(jù),不符合隔離性,也不符合一致性

例如:T 2 讀取一個(gè)數(shù)據(jù),T 1 對(duì)該數(shù)據(jù)做了修改。如果 T 2 再次讀取這個(gè)數(shù)據(jù),此時(shí)讀取的結(jié)果和第一次讀取的結(jié)果不同。

幻讀:事務(wù)A讀取到了事務(wù)B提交的新增數(shù)據(jù),不符合隔離性,也不符合一致性

例如:T 1 讀取某個(gè)范圍的數(shù)據(jù),T 2 在這個(gè)范圍內(nèi)插入新的數(shù)據(jù),T 1 再次讀取這個(gè)范圍的數(shù)據(jù),此時(shí)讀取的結(jié)果和和第一次讀取的結(jié)果不同。

產(chǎn)生并發(fā)性一致性問(wèn)題,那肯定是不符合一致性的,因?yàn)橹挥袧M(mǎn)足了一致性,事務(wù)的執(zhí)行結(jié)果才是正確的。

產(chǎn)生并發(fā)不一致性問(wèn)題主要原因是破壞了事務(wù)的隔離性,解決方法是通過(guò)并發(fā)控制來(lái)保證隔離性。并發(fā)控制可以通過(guò)封鎖來(lái)實(shí)現(xiàn),但是封鎖操作需要用戶(hù)自己控制,相當(dāng)復(fù)雜。數(shù)據(jù)庫(kù)管理系統(tǒng)提供了事務(wù)的隔離級(jí)別,讓用戶(hù)以一種更輕松的方式處理并發(fā)一致性問(wèn)題。

MySQL的共享鎖和排它鎖

1、共享鎖

共享鎖也叫讀鎖(Shared Lock),簡(jiǎn)稱(chēng)S鎖,原理:一個(gè)事務(wù)獲取了一個(gè)數(shù)據(jù)行的共享鎖,其他事務(wù)能獲得該行對(duì)應(yīng)的共享鎖,但不能獲得排他鎖,即一個(gè)事務(wù)在讀取一個(gè)數(shù)據(jù)行的時(shí)候,其他事務(wù)也可以讀,但不能對(duì)該數(shù)據(jù)行進(jìn)行增刪改。

2、排他鎖

排他鎖也叫寫(xiě)鎖(Exclusive Lock),簡(jiǎn)稱(chēng)x鎖,原理:一個(gè)事務(wù)獲取了一個(gè)數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的其他鎖(排他鎖或者共享鎖),即一個(gè)事務(wù)在讀取一個(gè)數(shù)據(jù)行的時(shí)候,其他事務(wù)不能對(duì)該數(shù)據(jù)行進(jìn)行增刪改查。

隔離級(jí)別

1、讀未提交(READ_UNCOMMITED)

(1)事務(wù)對(duì)當(dāng)前被讀取的數(shù)據(jù)不加鎖。

(2)事務(wù)在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對(duì)其加行級(jí)共享鎖,直到事務(wù)結(jié)束才釋放。

理解:1、事務(wù)B更改了某個(gè)數(shù)據(jù),此時(shí)加的是行級(jí)共享鎖,事務(wù)A還是可以讀取到這個(gè)更改了的數(shù)據(jù),如果事務(wù)B回滾,事務(wù)A讀取到的數(shù)據(jù)發(fā)生變化,造成臟讀。

2、事務(wù)A讀取某個(gè)數(shù)據(jù),事務(wù)B對(duì)其修改并提交,事務(wù)A再次讀取,得到的是不一樣的結(jié)果,造成不可重復(fù)讀

3、同理會(huì)造成幻讀,因?yàn)樵黾恿诵碌囊恍袛?shù)據(jù),那行數(shù)據(jù)沒(méi)有添加排它鎖

2、讀已提交(READ_COMMITED)

(1)事務(wù)對(duì)當(dāng)前被讀取的數(shù)據(jù)加行級(jí)共享鎖(當(dāng)讀到時(shí)才加鎖),一旦讀完該行,立即釋放該行級(jí)共享鎖。

(2)事務(wù)在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對(duì)其加行級(jí)排他鎖,直到事務(wù)結(jié)束才釋放。

理解:由(2)可以知道,事務(wù)B修改某個(gè)數(shù)據(jù)的時(shí)候,對(duì)當(dāng)前行添加了行級(jí)排它鎖,于是事務(wù)A直到事務(wù)結(jié)束才能訪問(wèn)這個(gè)數(shù)據(jù),如果這個(gè)數(shù)據(jù)發(fā)生了回滾,也不會(huì)造成臟讀,但如果數(shù)據(jù)沒(méi)有回滾,兩次查到的數(shù)據(jù)不一致,造成不可重復(fù)讀,也會(huì)造成幻讀,因?yàn)橹皇菍?duì)修改的行加了排它鎖,其他行沒(méi)有添加。

3、可重復(fù)讀(REPEATABLE_READ)

(1)事務(wù)在讀取某數(shù)據(jù)的瞬間(就是開(kāi)始讀取的瞬間),必須先對(duì)其加行級(jí)共享鎖,直到事務(wù)結(jié)束才釋放。

(2)事務(wù)在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對(duì)其加行級(jí)排他鎖,直到事務(wù)結(jié)束才釋放。

理解:事務(wù)A讀取某個(gè)數(shù)據(jù)的時(shí)候,添加了行級(jí)共享鎖,只能讀不能改,因此不會(huì)造成修改,也就不存在臟讀和不可重復(fù)讀,但是幻讀還是可能存在的,因?yàn)橹皇钱?dāng)前行添加了排它鎖,其他行沒(méi)有鎖。

4、可串行化(SERIALIZABLE)

(1)事務(wù)在讀取數(shù)據(jù)時(shí),必須先對(duì)其加表級(jí)共享鎖?,直到事務(wù)結(jié)束才釋放。

(2)事務(wù)在更新數(shù)據(jù)時(shí),必須先對(duì)其加表級(jí)排他鎖,直到事務(wù)結(jié)束才釋放。

理解:整個(gè)表都添加了鎖,也就不存在增刪改了,但是這樣會(huì)大大降低數(shù)據(jù)庫(kù)的性能,所以不建議使用這個(gè)隔離級(jí)別。

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

不可重復(fù)讀重點(diǎn)在于 updatedelete ,而幻讀的重點(diǎn)在于 insert。如果使用鎖機(jī)制來(lái)實(shí)現(xiàn)這兩種隔離級(jí)別,在可重復(fù)讀中,該 sql 第一次讀取到數(shù)據(jù)后,就將這些數(shù)據(jù)加鎖,其它事務(wù)無(wú)法修改這些數(shù)據(jù),就可以實(shí)現(xiàn)可重復(fù)讀了。但這種方法卻無(wú)法鎖住 insert 的數(shù)據(jù),所以當(dāng)事務(wù) A 先前讀取了數(shù)據(jù),或者修改了全部數(shù)據(jù),事務(wù) B 還是可以insert數(shù)據(jù)提交,這時(shí)事務(wù) A 就會(huì)發(fā)現(xiàn)莫名其妙多了一條之前沒(méi)有的數(shù)據(jù),這就是幻讀,不能通過(guò)行鎖來(lái)避免。需要 Serializable 隔離級(jí)別,讀用讀鎖,寫(xiě)用寫(xiě)鎖,讀鎖和寫(xiě)鎖互斥,這么做可以有效的避免幻讀、不可重復(fù)讀、臟讀等問(wèn)題,但會(huì)極大的降低數(shù)據(jù)庫(kù)的并發(fā)能力。所以說(shuō)不可重復(fù)讀和幻讀最大的區(qū)別,就在于如何通過(guò)鎖機(jī)制來(lái)解決他們產(chǎn)生的問(wèn)題。

MySQL默認(rèn)的隔離級(jí)別是:可重復(fù)讀(REPEATABLE_READ)

引用(本文章只供本人學(xué)習(xí)以及學(xué)習(xí)的記錄,如有侵權(quán),請(qǐng)聯(lián)系我刪除)

深入理解Mysql事務(wù)隔離級(jí)別

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容