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

- 活躍事務(wù)數(shù)組,針對(duì)可重復(fù)讀隔離級(jí)別,活躍事務(wù)列表是在事務(wù)啟動(dòng)瞬間,當(dāng)前正在“活躍”的所有事務(wù) ID,也即事務(wù)啟動(dòng)瞬間未提交的事務(wù)。
- 活躍事務(wù)數(shù)組最小值為低水位,活躍事務(wù)數(shù)組最大值加1為高水位。
例如:
活躍事務(wù)數(shù)組:【20,23,31】,低水位:20,高水位:32。
如何根據(jù)這些因素判斷數(shù)據(jù)值?
已數(shù)據(jù)行的db_trx_id為起始點(diǎn),延著回滾鏈取出db_trx_id按照下面規(guī)則判斷是否可見(jiàn),直到找到可見(jiàn)的數(shù)據(jù)才停止查找:
- db_trx_id <= 低水位,表示當(dāng)前事務(wù)早已經(jīng)提交,可見(jiàn)。
- db_trx_id >= 高水位,表示當(dāng)前事務(wù)還未提交,不可見(jiàn)。
- db_trx_id能在活躍事務(wù)列表找到,表示當(dāng)前事務(wù)還未提交,不可見(jiàn)。
- db_trx_id不能在活躍事務(wù)列表找到,表示當(dāng)前事務(wù)已提交,可見(jiàn)。
可重復(fù)讀和已提交讀區(qū)別?
可重復(fù)讀是在事務(wù)啟動(dòng)時(shí)創(chuàng)建視圖,已提交讀是在每條查詢SQL執(zhí)行時(shí)創(chuàng)建視圖。
視圖主要是用于記錄活躍(未提交)的事務(wù)ID列表。
串行化隔離級(jí)別的實(shí)現(xiàn)
讀的時(shí)候加共享鎖,也就是其他事務(wù)可以并發(fā)讀,寫的時(shí)候加排它鎖,其他事務(wù)不能并發(fā)寫也不能并發(fā)讀。
幻讀和可重復(fù)讀的區(qū)別?
都是在一個(gè)事務(wù)內(nèi)用相同的條件查詢兩次,但兩次的結(jié)果不一樣。差異在于,對(duì)不可重復(fù)讀來(lái)說(shuō),第二次的結(jié)果集相對(duì)第一次,有些記錄被修改(Update)或刪除(Delete)了。而幻讀是第二次結(jié)果集里出現(xiàn)了第一次結(jié)果集沒(méi)有的記錄(Insert)。
一個(gè)更加形象的說(shuō)法,幻讀是在第一次結(jié)果集的記錄“間隙”中增加了新的記錄。所以,MySQL將防止出現(xiàn)幻讀在可重復(fù)讀隔離級(jí)別下新增了間隙鎖(GapLock)。
為什么已提交讀隔離級(jí)別不能和statement格式binlog一起使用?
由于已提交讀隔離級(jí)別沒(méi)有間隙鎖,下面SQL不會(huì)存在阻塞。
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í)行日志時(shí),會(huì)把[6, 7]兩行數(shù)據(jù)也刪除掉。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
深入學(xué)習(xí)MySQL表數(shù)據(jù)操作
這篇文章主要介紹了深入學(xué)習(xí)MySQL表數(shù)據(jù)操作,基于表操作內(nèi)容圍繞主題展開(kāi)詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
通過(guò)SQL語(yǔ)句來(lái)備份,還原數(shù)據(jù)庫(kù)
這里僅僅用到了一種方式而已,把數(shù)據(jù)庫(kù)文件備份到磁盤然后在恢復(fù).2010-02-02
MySQL專用服務(wù)器自動(dòng)配置參數(shù)的實(shí)現(xiàn)
本文主要介紹了MySQL專用服務(wù)器自動(dòng)配置參數(shù)的實(shí)現(xiàn),MySQL8.0推出了專用數(shù)據(jù)庫(kù)服務(wù)器自動(dòng)配置參數(shù),通過(guò)打開(kāi)innodb_dedicated_server,下面就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下2024-09-09
Mysql關(guān)于進(jìn)程中的死鎖和解除鎖問(wèn)題
Mysql 經(jīng)常會(huì)遇到語(yǔ)句或者存儲(chǔ)過(guò)程長(zhǎng)時(shí)間沒(méi)有反應(yīng),大概率就是掛掉了,或者死鎖了,這篇文章主要介紹了Mysql關(guān)于進(jìn)程中的死鎖和解除鎖問(wèn)題,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
用VirtualBox構(gòu)建MySQL測(cè)試環(huán)境的筆記
這篇文章主要介紹了如何用VirtualBox構(gòu)建MySQL測(cè)試環(huán)境,特分享下,方便需要的朋友2013-08-08
mysql insert if not exists防止插入重復(fù)記錄的方法
在 MySQL 中,插入(insert)一條記錄很簡(jiǎn)單,但是一些特殊應(yīng)用,在插入記錄前,需要檢查這條記錄是否已經(jīng)存在,只有當(dāng)記錄不存在時(shí)才執(zhí)行插入操作,本文介紹的就是這個(gè)問(wèn)題的解決方案。2011-04-04

