1. 程式人生 > >mysql Innodb和mvcc

mysql Innodb和mvcc

本文主要解說mysql的Innodb儲存引擎和相關mvcc相關內容。下面的解說都是依據Innodb引擎。

mysql的常用的儲存引擎有Innodb和MyISAM兩種,因為Innodb支援事務、行級鎖、mvcc,因此5.7以後預設儲存引擎為Innodb,至於兩者更具體的細節,可以搜尋,這裡就不在說明。
mysql預設的事務隔離級別:可重複讀,即:保證同一事務內,兩次讀取同一資料,保證資料是一致的,不會發生更改。同時mysql通過mvcc機制,解決了髒讀問題。

MVCC 多版本併發控制協議(Multi-Version Concurrency Control)

詳細的多版本併發控制協議就不在詳細說明,想了解更多,可以搜尋檢視,下面主要介紹一下Innodb對mvcc的實現。
在InnoDB的MVCC,在每行記錄後面儲存兩個隱藏的列來實現的,這兩個列,分別儲存了該行的建立時間(ctime),一個儲存的是行的刪除時間(dtime)。這裡儲存的並不是實際的時間值,而是系統版本號(也可以理解為事務的ID),每開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的ID,這樣就保證每個事務ID的唯一性。

1 insert操作

每次插入的時候,把當前系統版本號作為ctime的版本號,如果插入的版本號大於查詢事務的版本號,那麼肯定不會發生髒讀,如果小於,會不會出現髒讀。例如剛才查詢時,事務5先啟動,然後進行了插入操作,並且提交了,那麼事務6是否可以檢視到?等待下篇文章分析。

2 select操作

每次查詢都會有兩個隱藏條件,只查詢ctime不大於當前事務id和dtime小於當前事務id的行,這樣就排除了其他事務新增、刪除的資料。
特例:如果事務ID為5,什麼也不做,當事務6查詢時,事務5新增一條資料,但是還沒有提交,那麼該條資料的事務id為5,那麼事務6再次查詢時會不會查到事務5新增的資料?
說明:(1) mysql的預設事務是讀已提交和可重複讀,無論是那種隔離級別,都不會發生事務6讀取事務5新增的資料,這涉及到mysql的快取問題,等待下一篇討論。
(2) 如果事務5已經提交了,那麼事務6是否可以讀取到呢?具體等待下一篇討論。

3 delete操作

刪除資料,並不會立刻刪除資料,而是把dtime的版本號設定為當前事務ID。這樣同一事務內的查詢是不會有影響的,因為當前的刪除版本號大於查詢的版本號。

4 update操作

mysql進行更新時,並不是直接在原資料上進行修改。實際上是新插入了一行記錄,並儲存其建立時間為當前事務的ID,同時儲存當前事務ID到要UPDATE的行的刪除時間。這樣就新增的修改資料的版本號大於當前查詢的版本號,因此其他事務的修改,並不影響當前事務的查詢,如果:修改的版本號低於當前查詢的版本號,並且修改的事務已經提交了,如何保證可重複讀?