<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
MVCC(Multi-Version Concurrency Control)多版本並行控制,是用來在資料庫中控制並行的方法,實現對資料庫的並行存取用的。在MySQL中,MVCC只在讀取已提交(Read Committed)和可重複讀(Repeatable Read)兩個事務級別下有效。其是通過Undo紀錄檔中的版本鏈和ReadView一致性檢視來實現的。MVCC就是在多個事務同時存在時,SELECT語句找尋到具體是版本鏈上的哪個版本,然後在找到的版本上返回其中所記錄的資料的過程。
首先需要知道的是,在MySQL中,會預設為我們的表後面新增三個隱藏欄位:
注意,新增的隱藏欄位並不是很多人認為的建立時間和刪除時間,同時在MySQL中MVCC的實現也不是通過什麼快照來實現的。之所以有這種說法可能是源自於《高效能MySQL》一書中對MySQL中MVCC的錯誤結論,然後就人云亦云傳開了(注意,我這裡一直強調的是MySQL中MVCC的實現,是因為在不同的資料庫中可能會有不同的實現)。所以說看原始碼和看官方檔案才是最權威的解釋)
很多人在談起mysql事務的時候都能很快的答出mysql的幾種事務隔離級別,以及在各自隔離級別下產生的問題,但是一旦談到為什麼會產生這樣的結果時會覺得難以回答,說到底,還是對底層的原理未做深入的探究,本篇將從較為底層的原理層面來聊聊關於mysql的mvcc原理,瞭解並掌握了mvcc原理,也就能真正回答這些問題了。
在瞭解mvcc原理之前,先來看下面這種圖,這是一張關於使用者端發起一條update 資料的語句時,mysql 的innodb引擎所作的一些列操作過程(可按照前面的序列號);
從這張圖,我們提取如下關鍵資訊:
從上面的分析中,可以看出,redolog檔案在整個執行過程中起到了非常重要的作用,有必要對該檔案做一些深入的瞭解和學習;
又叫重做紀錄檔,記錄的是事務提交時資料頁的物理修改,用來實現事務的永續性
redo log 紀錄檔檔案由兩部分組成:
仍然以上面流程圖中的更新一條資料的事務過程分析,來看redolog的整體流轉過程
具體步驟如下:
在 InnoDB引擎中的記憶體結構中,主要記憶體區域就是緩衝池, 在緩衝池中快取了很多的數 據頁(磁碟中讀取mysql資料時一般以資料頁為單位進行載入); 在一個事務執行中,比如執行多個增刪改的操作時, InnoDB 引擎會先操作緩衝池中的資料,如果 緩衝區沒有對應的資料,再通過後臺執行緒將磁碟中資料load出來,放到緩衝區,然後修改緩衝池中 的資料,修改後的資料頁我們稱為髒頁; 而髒頁則會在一定的時機,通過後臺執行緒重新整理到磁碟中,從而保證緩衝區與磁碟的資料一致。 但是緩衝區髒頁資料並不是實時重新整理的,而是隔一段時間後才將緩衝區的資料刷到磁碟中。 假如重新整理到磁碟的過程出錯了,而提示給使用者事務提交成功,而資料卻 沒有持久化下來,這就出現問題了,沒有保證事務的永續性。 有了 redolog 之後,當對緩衝區的資料進行增刪改之後,會首先將操作的資料頁的變化,記錄在 redo log buffer中。在事務提交時,會將 redo log buffer 中的資料重新整理到 redo log 磁碟檔案中。 過一段時間後,如果重新整理緩衝區的髒頁到磁碟時,發生錯誤,此時就可以藉助於 redo log 進行資料 恢復,這樣就保證了事務的永續性。 而如果髒頁成功重新整理到磁碟 或 或者涉及到的資料已經落盤,此 時redolog 就沒有作用了,就可以刪除了,所以存在的兩個 redolog 檔案是迴圈寫的。 說到這裡就有夥伴要問,為什麼每一次提交事務,要重新整理 redo log 到磁碟中呢,而不是直接將 buffer pool 中的髒頁重新整理 到磁碟呢? 因為使用者端與mysql進行資料互動(IO)過程中,們運算元據一般都是隨機讀寫磁碟的(隨機讀寫比較慢),而不是順序讀寫磁碟(順序讀寫塊)。 而 redo log 在 往磁碟檔案中寫入資料,由於是紀錄檔檔案,所以都是順序寫的。順序寫的效率,要遠大於隨機寫。 這 種先寫紀錄檔的方式,也稱之為 WAL ( Write-Ahead Logging )。
undo log 也成為回滾紀錄檔,用於記錄資料被修改前的資訊 , 作用包含兩個 : 提供回滾 ( 保證事務的原子性 ) 和 MVCC(多版本並行控制 ) 。
舉例來說,本次使用update語句修改了一條id為1的資料,如果事務提交失敗,那麼就需要回滾資料,mysql引擎怎麼知道回滾到哪裡呢?那就要藉助undo log了,undolog中記錄了修改之前的資料,所以就可以用於事務回滾。
從文章開頭的流程圖中再簡單抽象出下面的簡化執行步驟
在開啟一個事務對一條資料記錄進行update的時候,對於這條資料行來說,其底層儲存的結構大概長下面這樣;
在這行記錄中,對應著兩個隱藏欄位,事務ID和回滾指標,當執行一條insert語句時,
begin ; insert into user (name) values ( "tom" );
對於 undolog 來說,記錄的資料狀態將會呈現如下效果,可以看到,在這條記錄中,回滾指標指向了一條資料激勵,記錄了這條資料的源資訊,通過一個undo no標識;
執行update的時候,資料行記錄變更,同時在redo log 回滾指標鏈上將增加一條記錄,並連線上一條記錄;
繼續執行一個update語句:
UPDATE user SET name ='jike' WHERE id= 1 ;
如果事務回滾,執行rollback,對應的流程如下:
undo log的刪除分成2種
全稱:多版本並行控制,MVCC 是通過資料行的多個版本管理來實現資料庫的並行控制。通過這項技術,使得在InnoDB的事務隔離級別下執行 一致性讀操作有了保證。換言之,就是為了查詢一些正在被另一個事務更新的資料行,並且可以看到它們被更新之前的值,這樣在做查詢的時候就不用等待另一個事務釋放鎖。
mvcc的實現主要依賴下面的3個主要邏輯實現,分別是:
MVCC在MySQL InnoDB中的實現主要是為了提高資料庫並行效能,用更好的方式去處理讀-寫衝突,這樣即使有讀寫衝突時,也能做到不加鎖,非阻塞並行讀 ,而這個讀指的就是快照讀,而非當前讀。當前讀實際上是一種加鎖的操作,是悲觀鎖的實現,而MVCC本質是採用樂觀鎖思想的一種方式。
快照讀又叫一致性讀,讀取的是快照資料。不加鎖的簡單的 SELECT 都屬於快照讀,即不加鎖的非阻塞讀;比如這樣:
SELECT * FROM player WHERE ...
之所以出現快照讀的情況,是基於提高並行效能的考慮,快照讀的實現是基於MVCC,它在很多情況下,避免了加鎖操作,降低了開銷。
既然是基於多版本,那麼快照讀可能讀到的並不一定是資料的最新版本,而有可能是之前的歷史版本。快照讀的前提是隔離級別不是序列級別,序列級別下的快照讀會退化成當前讀。
當前讀讀取的是記錄的最新版本(最新資料,而不是歷史版本的資料),讀取時還要保證其他並行事務不能修改當前記錄,會對讀取的記錄進行加鎖。加鎖的 SELECT,或者對資料進行增刪改都會進行當前讀。比如:
SELECT * FROM student LOCK IN SHARE MODE; # 共用鎖 SELECT * FROM student FOR UPDATE; # 排他鎖 INSERT INTO student values ... # 排他鎖 DELETE FROM student WHERE ... # 排他鎖
來看下面這一些列的事務操作過程,如下是一組操作同一條資料的記錄的多個事務,從事務2 ~ 事務5,分別對應不同的操作何階段;
從上文我們對undolog的瞭解,每次修改一條資料時,會在undolog 回滾鏈中增加一條記錄,用於後續做資料回滾;
具體步驟如下:
比如當事務2執行第一條修改語句時,會記錄一條undo log紀錄檔,記錄了當前資料變更之前的樣子; 然後更新記錄,並且記錄本次操作的事務ID,回滾指標,回滾指標用來指定如果發生回滾,回滾到哪一個版本;
當事務 3 執行第一條修改語句時,也會記錄 undo log 紀錄檔,記錄資料變更之前的樣子 ; 然後更新記 錄,並且記錄本次操作的事務 ID ,回滾指標,回滾指標用來指定如果發生回滾,回滾到哪一個版本;
當事務 4 執行第一條修改語句時,也會記錄 undo log 紀錄檔,記錄資料變更之前的樣子 ; 然後更新記 錄,並且記錄本次操作的事務 ID ,回滾指標,回滾指標用來指定如果發生回滾,回滾到哪一個版本;
通過上面一些列的操作,最終會發現,不同事務或相同事務對同一條記錄進行修改,會導致該記錄的 undolog 生成一條 記錄版本連結串列,連結串列的頭部是最新的舊記錄,連結串列尾部是最早的舊記錄。
有了上面的redo log 的回鏈,最終是怎麼確定某個事務讀取的資料是長什麼樣子呢?接下來 readview就派上用場了;
ReadView (讀檢視)是 快照讀 SQL 執行時 MVCC 提取資料的依據,記錄並維護系統當前活躍的事務 (未提交的)id;
ReadView中包含了四個核心欄位:
欄位 | 含義 |
m_ids | 當前活躍事務 ID 集合 |
min_trx_id | 最小活躍事務 ID |
max_trx_id | 預分配事務 ID ,當前最大事務 ID+1 (因為事務 ID 是自增的) |
creator_trx_id | ReadView 建立者事務 ID |
而在 readview 中就規定了版本鏈資料的存取規則,
trx_id 代表當前undolog版本鏈對應事務ID
完整的匹配規則如下:
條件 | 是否可以存取 | 說明 |
trx_id ==
creator_trx_id | 可以存取該版本 | 成立,說明資料是當前這個事
務更改的 |
trx_id < min_trx_id | 可以存取該版本 | 成立,說明資料已經提交了 |
trx_id > max_trx_id | 不可以存取該版本 | 成立,說明該事務是在
ReadView 生成後才開啟 |
min_trx_id <= trx_id
<= max_trx_id | 如果 trx_id 不在 m_ids 中,
是可以存取該版本的 | 成立,說明資料已經提交 |
不同的隔離級別,生成ReadView的時機不同:
也就是說,在利用mvcc的多版本並行控制時,只需要關注這兩種事務隔離級別就行了,接下來,以上午的excel中展示的幾個事務為例,對照這兩種型別的事務隔離級別進行說明;
以事務5為例進行說明,兩次快照讀讀取資料時,是如何獲取資料的?
在事務 5 中,查詢了兩次 id 為 30 的記錄,由於隔離級別為 Read Committed ,所以每一次進行快照讀 都會生成一個 ReadView ,那麼兩次生成的 ReadView 如下
那麼這兩次快照讀在獲取資料時,就需根據所生成的 ReadView 以及 ReadView 的版本鏈存取規則, 到undolog 版本鏈中匹配資料,最終決定此次快照讀返回的資料; 先來看第一次快照讀具體的讀取過程
對應的undo log 版本鏈如下
在進行匹配時,會從undo log的版本鏈,從上到下進行挨個匹配:
1)先匹配下面這條記錄,這條記錄對應的trx_id為4,也就是將4帶入右側的匹配規則中。 ①不滿足 ②不滿足 ③不滿足 ④也不滿足 , 都不滿足,則繼續匹配undo log版本鏈的下一條;
2) 再匹配第二條記錄, 這條 記錄對應的 trx_id 為 3 ,也就是將 3 帶入右側的匹配規則中。①不滿足 ②不滿足 ③不滿足 ④也 不滿足 ,都不滿足,則繼續匹配 undo log 版本鏈的下一條;
3)再匹配第三條記錄,這條記 錄對應的trx_id為2,也就是將2帶入右側的匹配規則中。①不滿足 ②滿足 終止匹配,此次快照 讀,返回的資料就是版本鏈中記錄的這條資料;
再來看第二次快照讀具體的讀取過程:
對應的undolog 版本鏈如下:
在進行匹配時,會從 undo log 的版本鏈,從上到下進行挨個匹配:
1)先匹配這條記錄,這條記錄對應的 trx_id為4,也就是將4帶入右側的匹配規則中。 ①不滿足 ②不滿足 ③不滿足 ④也不滿足 , 都不滿足,則繼續匹配undo log版本鏈的下一條;
2)再匹配第二條, 這條 記錄對應的 trx_id 為 3 ,也就是將 3 帶入右側的匹配規則中。①不滿足 ②滿足 。終止匹配,此次 快照讀,返回的資料就是版本鏈中記錄的這條資料;
在這種隔離級別下,僅在事務中第一次執行快照讀時生成 ReadView ,後續繼續複用該 ReadView 。 而 可重複讀在一個事務中,執行兩次相同的select 語句,查詢到的結果是一樣的; 那 MySQL 是如何做到可重複讀的呢 ? 按照上面的過程做一下類似的分析
可以看到,在可重複讀這種事務 隔離級別下,只在事務中第一次快照讀時生成 ReadView ,後續都複用該 ReadView。既然 ReadView 都一樣, ReadView 版本鏈匹配規則也一樣, 最終快照讀返 回的結果也是一樣的了。 總結 MVCC實現原理是通過 InnoDB表的隱藏欄位、UndoLog 版本鏈、ReadView來實現的;MVCC + 鎖,則實現了事務的隔離性;一致性則是由redolog 與 undolog保證;
到此這篇關於mysql mvcc 原理詳解的文章就介紹到這了,更多相關mysql mvcc 原理內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45