Mysql隔離性之Read View的用法說(shuō)明
當(dāng)前事務(wù)能讀取到哪個(gè)歷史版本?
Read View是事務(wù)開(kāi)啟時(shí),當(dāng)前所有事務(wù)的一個(gè)集合,這個(gè)數(shù)據(jù)結(jié)構(gòu)中存儲(chǔ)了當(dāng)前Read View中最大的ID及最小的ID。
這就是當(dāng)前活躍事務(wù)列表,如下所示:
ct-trx --> trx11 --> trx9 --> trx6 --> trx5 --> trx3;
ct-trx 表示當(dāng)前事務(wù)的id,對(duì)應(yīng)上面的read_view數(shù)據(jù)結(jié)構(gòu)如下,
read_view->creator_trx_id = ct-trx; read_view->up_limit_id = trx3; 低水位 read_view->low_limit_id = trx11; 高水位 read_view->trx_ids = [trx11, trx9, trx6, trx5, trx3];
low_limit_id是“高水位”,即當(dāng)時(shí)活躍事務(wù)的最大id,如果讀到row的db_trx_id>=low_limit_id,說(shuō)明這些id在此之前的數(shù)據(jù)都沒(méi)有提交,如注釋中的描述,這些數(shù)據(jù)都不可見(jiàn)。
if (trx_id >= view->low_limit_id) { return(FALSE); }
注:readview 部分源碼
up_limit_id是“低水位”,即當(dāng)時(shí)活躍事務(wù)列表的最小事務(wù)id,如果row的db_trx_id<up_limit_id,說(shuō)明這些數(shù)據(jù)在事務(wù)創(chuàng)建id的時(shí)都已經(jīng)提交,如注釋中的描述,這些數(shù)據(jù)均可見(jiàn)。
if (trx_id < view->up_limit_id) { return(TRUE); }
row的db_trx_id在low_limit_id和up_limit_id之間,則查找該記錄的db_trx_id是否在自己事務(wù)的read_view->trx_ids列表中,如果在則該記錄的當(dāng)前版本不可見(jiàn),否則該記錄的當(dāng)前版本可見(jiàn)。
不同隔離級(jí)別ReadView實(shí)現(xiàn)方式
1. read-commited:
即:在每次語(yǔ)句執(zhí)行的過(guò)程中,都關(guān)閉read_view, 重新在row_search_for_mysql函數(shù)中創(chuàng)建當(dāng)前的一份read_view。這樣就會(huì)產(chǎn)生不可重復(fù)讀現(xiàn)象發(fā)生。
2. repeatable read:
在repeatable read的隔離級(jí)別下,創(chuàng)建事務(wù)trx結(jié)構(gòu)的時(shí)候,就生成了當(dāng)前的global read view。使用trx_assign_read_view函數(shù)創(chuàng)建,一直維持到事務(wù)結(jié)束。在事務(wù)結(jié)束這段時(shí)間內(nèi) 每一次查詢(xún)都不會(huì)重新重建Read View , 從而實(shí)現(xiàn)了可重復(fù)讀。
補(bǔ)充:mysql的mvcc和readview
隔離級(jí)別標(biāo)準(zhǔn)定義:
read uncommited 一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)未提交的結(jié)果(可能發(fā)生回滾),叫臟讀,這會(huì)帶來(lái)臟讀、幻讀、不可重復(fù)讀問(wèn)題
read commited 一個(gè)事務(wù)a讀取到了另一個(gè)事務(wù)b最新提交的結(jié)果,使得事務(wù)a兩次讀取的結(jié)果不同,其避免了臟讀,會(huì)出現(xiàn)不可重復(fù)讀,幻讀,通過(guò)版本鏈(mvcc)和readview實(shí)現(xiàn)。
repeatable read(mysql的默認(rèn)隔離級(jí)別) 一個(gè)事務(wù)第一次讀過(guò)某條記錄后,另一個(gè)事務(wù)修改提交了該條記錄后,事務(wù)a讀取到的還是第一次的值,這就是可重復(fù)讀,同一個(gè)事務(wù)中多次讀取相同的數(shù)據(jù)返回的結(jié)果是一樣的。事務(wù)不會(huì)讀到其他事務(wù)對(duì)已有數(shù)據(jù)的修改,即使其他事務(wù)已提交,也就是說(shuō),事務(wù)開(kāi)始時(shí)讀到的已有數(shù)據(jù)是什么,在事務(wù)提交前的任意時(shí)刻,這些數(shù)據(jù)的值都是一樣的。但是,對(duì)于其他事務(wù)新插入的數(shù)據(jù)是可以讀到的,這也就引發(fā)了幻讀問(wèn)題。其避免了臟讀和不可重復(fù)讀問(wèn)題,但幻讀依然存在。還是會(huì)出現(xiàn)幻讀,(但是mysql解決了幻讀的問(wèn)題),通過(guò)版本鏈和readview實(shí)現(xiàn)
serializable 不允許對(duì)同一行記錄的讀和寫(xiě)的并發(fā)操作,必需串行執(zhí)行,所以不會(huì)出現(xiàn)幻讀,臟讀現(xiàn)象
在mysql中讀已提交和可重復(fù)讀事務(wù)隔離級(jí)別是通過(guò)mvcc和readview實(shí)現(xiàn)的
mvcc即Multi-Version Concurrency Control,多版本并發(fā)控制,維護(hù)一個(gè)數(shù)據(jù)的多個(gè)版本,使得事務(wù)之間的讀寫(xiě)按照隔離級(jí)別獲取相應(yīng)的結(jié)果,不發(fā)生沖突
對(duì)于隔離級(jí)別read committed,每次都生成一個(gè)新的readview
對(duì)于隔離級(jí)別repeatable read,只在事務(wù)開(kāi)啟時(shí),生成一個(gè)readview,直到事務(wù)提交,不發(fā)生變化,所以可以保證可重復(fù)讀。
生成readview時(shí)
m_ids:表示活躍事務(wù)id列表
min_trx_id:活躍事務(wù)中的最小事務(wù)id
max_trx_id:已創(chuàng)建的最大事務(wù)id
creator_trx_id:當(dāng)前的事務(wù)id
對(duì)當(dāng)前事務(wù)來(lái)說(shuō),按照以下規(guī)則從最新的版本開(kāi)始遍歷,獲取對(duì)應(yīng)的版本記錄。
1、被訪問(wèn)的trx_id與readview中的creator_trx_id相同,表示當(dāng)前事務(wù)在訪問(wèn)自己修改的記錄,可見(jiàn),返回;
2、被訪問(wèn)的trx_id小于min_trx_id,表明該版本已提交,可見(jiàn),返回;
3、被訪問(wèn)的trx_id大于等于max_trx_id,表明該版本在生成readview時(shí),還未開(kāi)啟,不可見(jiàn),返回;
4、被訪問(wèn)的trx_id在min_trx_id和max_trx_id之間,判斷是否在m_ids中,如果在,則說(shuō)明生成readview時(shí),該版本事務(wù)未提交,該版本不可見(jiàn);如果不在,則說(shuō)明生成readview時(shí),該版本事務(wù)已提交可見(jiàn),返回。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
一鍵搭建MYSQL主從,輕松應(yīng)對(duì)數(shù)據(jù)備份與恢復(fù)
MYSQL主從是一種常見(jiàn)的數(shù)據(jù)庫(kù)架構(gòu),它可以提高數(shù)據(jù)庫(kù)的可用性和性能,在主從架構(gòu)中,主數(shù)據(jù)庫(kù)負(fù)責(zé)處理寫(xiě)操作,而從數(shù)據(jù)庫(kù)負(fù)責(zé)處理讀操作,當(dāng)主數(shù)據(jù)庫(kù)發(fā)生故障時(shí),從數(shù)據(jù)庫(kù)可以接管并繼續(xù)提供服務(wù),從而實(shí)現(xiàn)高可用性,需要的朋友可以參考下2023-10-10淺談MySQL 統(tǒng)計(jì)行數(shù)的 count
這篇文章主要介紹了MySQL 統(tǒng)計(jì)行數(shù)的 count的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07windows環(huán)境下Mysql中文亂碼問(wèn)題解決方法
在搭建Mysql環(huán)境的時(shí)候遇到了中文亂碼問(wèn)題,下面與大家分享下具體的解決方法,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-06-06MySQL中SQL分頁(yè)查詢(xún)的幾種實(shí)現(xiàn)方法及優(yōu)缺點(diǎn)
這篇文章主要介紹了MySQL中SQL分頁(yè)查詢(xún)的幾種實(shí)現(xiàn)方法及優(yōu)缺點(diǎn), 分頁(yè)查詢(xún)就是在滿(mǎn)足條件的一堆有序數(shù)據(jù)中截取當(dāng)前所需要展示的那部分。對(duì)此感興趣的可以來(lái)了解一下2020-07-07Mysql優(yōu)化之Zabbix分區(qū)優(yōu)化
這篇文章主要介紹了Mysql優(yōu)化中Zabbix分區(qū)優(yōu)化的詳細(xì)方法和優(yōu)缺點(diǎn)分析,一起學(xué)習(xí)下。2017-11-11lnmp重置mysql數(shù)據(jù)庫(kù)root密碼的兩種方法
這篇文章給大家介紹了lnmp重置mysql數(shù)據(jù)庫(kù)root密碼的兩種方法,第一種方法通過(guò)腳本重置密碼,第二種方法通過(guò)命令修改,具體操作方法大家參考下本文2017-07-07mysql查詢(xún)的時(shí)候給字段賦默認(rèn)值操作
這篇文章主要介紹了mysql查詢(xún)的時(shí)候給字段賦默認(rèn)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10