MySQL - 并发事务问题及解决方案
文章目錄
- 生猛干貨
- Pre
- 臟讀
- 不可重復(fù)讀
- 幻讀
- Solutions
- 搞定MySQL
生猛干貨
帶你搞定MySQL實(shí)戰(zhàn),輕松對(duì)應(yīng)海量業(yè)務(wù)處理及高并發(fā)需求,從容應(yīng)對(duì)大場(chǎng)面試
Pre
MySQL - 多版本控制 MVCC 機(jī)制初探
中我們初步了解了 MVCC 的原理及其實(shí)現(xiàn)。 隨著數(shù)據(jù)庫并發(fā)事務(wù)處理能力的增強(qiáng),數(shù)據(jù)庫資源的利用率也會(huì)大大提高,從而提高了數(shù)據(jù)庫系統(tǒng)的事務(wù)吞吐量,可以支持更多的用戶并發(fā)訪問。
但并發(fā)事務(wù)處理也會(huì)帶來一些問題,如:臟讀、不可重復(fù)讀、幻讀等等
臟讀
一個(gè)事務(wù)正在對(duì)一條記錄做修改,在這個(gè)事務(wù)完成并提交前,這條記錄的數(shù)據(jù)就處于不一致狀態(tài);這時(shí),另一個(gè)事務(wù)也來讀取同一條記錄,如果不加控制,第二個(gè)事務(wù)讀取了這些“臟”數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會(huì)產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被形象的叫作"臟讀"(Dirty Reads)。
簡(jiǎn)答來說,讀取了其他事務(wù)未提交的數(shù)據(jù)
不可重復(fù)讀
一個(gè)事務(wù)在讀取某些數(shù)據(jù)后的某個(gè)時(shí)間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變、或某些記錄已經(jīng)被刪除了!這種現(xiàn)象就叫作“ 不可重復(fù)讀”(Non-Repeatable Reads)。
幻讀
一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀”(Phantom Reads)。
Solutions
MySQL 數(shù)據(jù)庫是通過事務(wù)隔離級(jí)別來解決上述問題的。
我們舉例說明“臟讀”和“不可重復(fù)讀”的問題
【 RC 隔離級(jí)別】
MySQL 中默認(rèn)的事務(wù)隔離級(jí)別是 RR,這里設(shè)置成 RC 隔離級(jí)別,此時(shí)提交事務(wù) B 修改 id=1 的數(shù)據(jù)之后,事務(wù) A 進(jìn)行同樣的查詢操作,后一次和前一次的查詢結(jié)果不一樣,這就是不可重復(fù)讀(重新讀取產(chǎn)生的結(jié)果不一樣了)。這里事務(wù) A 讀到了事務(wù) B 提交的數(shù)據(jù),即是“臟讀”。
【RR隔離級(jí)別】
下面我們來看看在mysql默認(rèn)的RR隔離級(jí)別下的情況。當(dāng) teacher_id=1時(shí),事務(wù) A 先進(jìn)行一次讀取操作,事務(wù) B 中間修改了 id=1 的數(shù)據(jù)并提交,事務(wù) C 也插入了一條數(shù)據(jù)并提交。事務(wù) A 第二次讀到的數(shù)據(jù)和第一次完全相同。所以說它是可重讀的。
【幻讀】
行鎖可以防止不同事務(wù)版本的數(shù)據(jù)在修改提交時(shí)造成數(shù)據(jù)沖突的情況。但如何避免別的事務(wù)插入數(shù)據(jù)造成的問題呢。我們先來看看在 RC 隔離級(jí)別下的處理過程。
如下圖所示,事務(wù) A 修改了所有 teacher_id=30 的數(shù)據(jù),但是當(dāng)事務(wù) B INSERT 新數(shù)據(jù)后,事務(wù) A 發(fā)現(xiàn)莫名其妙的多了一行 teacher_id=30 的數(shù)據(jù), 而且沒有被之前的 UPDATE語句所修改,這就是“當(dāng)前讀”的幻讀問題。
跟上面的例子一樣,也是在 RC 事務(wù)隔離級(jí)別下,這時(shí)事務(wù) B INSERT 了一條數(shù)據(jù),并提交,而事務(wù) A 讀到了事務(wù) B 新插入的數(shù)據(jù)。這也是幻讀,如下圖所示。
這里就需要重點(diǎn)注意不可重復(fù)讀和幻讀的區(qū)別了。前面講了它們的含義,這個(gè)提醒大家的是:不可重復(fù)讀重點(diǎn)在于 UPDATA 和 DELETE,而幻讀的重點(diǎn)在于 INSERT。它們之間最大的區(qū)別是如何通過鎖機(jī)制來解決它們產(chǎn)生的問題。這里說的鎖只是使用悲觀鎖機(jī)制。
那么在 RR 隔離級(jí)別下,事務(wù) A 在 UPDATE 后加鎖,事務(wù) B 無法插入新數(shù)據(jù),這樣事務(wù) A在 UPDATE 前后讀的數(shù)據(jù)保持一致,避免了幻讀。
跟上面的案例一樣,也是在 RR 事務(wù)隔離級(jí)別下,事務(wù) A 在 UPDATE 后加鎖,對(duì)于其他兩個(gè)事務(wù),事務(wù) B 和事務(wù) C 的 INSERT 操作,就必須等事務(wù) A 提交后,才能繼續(xù)執(zhí)行。這里就用到了“鎖”,這里使用的是 Gap 鎖,后面會(huì)詳細(xì)講解。它和上面的情況一樣,解決了“幻讀”的發(fā)生,如下圖所示。
搞定MySQL
總結(jié)
以上是生活随笔為你收集整理的MySQL - 并发事务问题及解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL - 多版本控制 MVCC 机
- 下一篇: linux cmake编译源码,linu