MySQL中隔離級別的使用詳解
引言
在MySQL中,事務隔離級別和二進制日志(binlog)的格式密切相關,直接影響數(shù)據(jù)的一致性和復制的正確性。
尤其是在“已提交讀”(Read Committed)隔離級別下,由于沒有使用間隙鎖,某些并發(fā)操作在執(zhí)行過程中不會產(chǎn)生阻塞,但在采用基于語句(statement-based)的binlog格式時,可能導致主從復制中數(shù)據(jù)順序和一致性的問題。
例如,某些事務雖然在執(zhí)行順序上先后提交,但在binlog中記錄的順序未必反映真實執(zhí)行順序,進而引發(fā)數(shù)據(jù)異常刪除等情況。
本文將圍繞已提交讀隔離級別與statement格式binlog的兼容性問題展開探討,揭示其潛在風險及影響,幫助讀者更好地理解MySQL事務隔離與復制機制的細節(jié)。
undo log的作用
- 事務發(fā)生錯誤時回滾rollback,數(shù)據(jù)更新之前,會把原始數(shù)據(jù)保存在undo log中,保證事務出錯回滾或者我們手動回滾的時候,能夠在undo log中找到最初的數(shù)據(jù)。
- 提供了MVCC的非鎖定讀(快照讀),依賴undo log實現(xiàn)。
MVCC的實現(xiàn)有以下幾個重要因素
- 數(shù)據(jù)行的兩個隱藏字段,db_trx_id(事務id)、db_roll_ptr(回滾指針),回滾指針指向拷貝的undo log副本記錄。

- 活躍事務數(shù)組,針對可重復讀隔離級別,活躍事務列表是在事務啟動瞬間,當前正在“活躍”的所有事務 ID,也即事務啟動瞬間未提交的事務。
- 活躍事務數(shù)組最小值為低水位,活躍事務數(shù)組最大值加1為高水位。
例如:
活躍事務數(shù)組:【20,23,31】,低水位:20,高水位:32。
如何根據(jù)這些因素判斷數(shù)據(jù)值?
已數(shù)據(jù)行的db_trx_id為起始點,延著回滾鏈取出db_trx_id按照下面規(guī)則判斷是否可見,直到找到可見的數(shù)據(jù)才停止查找:
- db_trx_id <= 低水位,表示當前事務早已經(jīng)提交,可見。
- db_trx_id >= 高水位,表示當前事務還未提交,不可見。
- db_trx_id能在活躍事務列表找到,表示當前事務還未提交,不可見。
- db_trx_id不能在活躍事務列表找到,表示當前事務已提交,可見。
可重復讀和已提交讀區(qū)別?
可重復讀是在事務啟動時創(chuàng)建視圖,已提交讀是在每條查詢SQL執(zhí)行時創(chuàng)建視圖。
視圖主要是用于記錄活躍(未提交)的事務ID列表。
串行化隔離級別的實現(xiàn)
讀的時候加共享鎖,也就是其他事務可以并發(fā)讀,寫的時候加排它鎖,其他事務不能并發(fā)寫也不能并發(fā)讀。
幻讀和可重復讀的區(qū)別?
都是在一個事務內(nèi)用相同的條件查詢兩次,但兩次的結(jié)果不一樣。差異在于,對不可重復讀來說,第二次的結(jié)果集相對第一次,有些記錄被修改(Update)或刪除(Delete)了。而幻讀是第二次結(jié)果集里出現(xiàn)了第一次結(jié)果集沒有的記錄(Insert)。
一個更加形象的說法,幻讀是在第一次結(jié)果集的記錄“間隙”中增加了新的記錄。所以,MySQL將防止出現(xiàn)幻讀在可重復讀隔離級別下新增了間隙鎖(GapLock)。
為什么已提交讀隔離級別不能和statement格式binlog一起使用?
由于已提交讀隔離級別沒有間隙鎖,下面SQL不會存在阻塞。
tx1 begin; tx1 delete id>5 and id<10; tx2 begin; tx2 insert into values(6)(7); tx2 commit; tx1 commit;
tx2先提交到binlog,tx1后提交到binlog,binlog按照順序執(zhí)行日志時,會把[6, 7]兩行數(shù)據(jù)也刪除掉。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
MySQL專用服務器自動配置參數(shù)的實現(xiàn)
本文主要介紹了MySQL專用服務器自動配置參數(shù)的實現(xiàn),MySQL8.0推出了專用數(shù)據(jù)庫服務器自動配置參數(shù),通過打開innodb_dedicated_server,下面就來詳細的介紹一下,感興趣的可以了解一下2024-09-09
用VirtualBox構建MySQL測試環(huán)境的筆記
這篇文章主要介紹了如何用VirtualBox構建MySQL測試環(huán)境,特分享下,方便需要的朋友2013-08-08
mysql insert if not exists防止插入重復記錄的方法
在 MySQL 中,插入(insert)一條記錄很簡單,但是一些特殊應用,在插入記錄前,需要檢查這條記錄是否已經(jīng)存在,只有當記錄不存在時才執(zhí)行插入操作,本文介紹的就是這個問題的解決方案。2011-04-04

