mysql6 MVCC多版本併發控制

2021-10-25 19:04:49 字數 3499 閱讀 2299

1、什麼是mvcc?

mvcc全稱multi-version concurrency control,即多版本併發控制。mvcc是一種併發控制的方法,一般在資料庫管理系統中,實現對資料庫的併發訪問,在程式語言中實現事務記憶體。

mvcc在mysql innodb中的實現主要是為了提高資料庫併發效能,用更好的方式去處理讀-寫衝突,做到即使有讀寫衝突時,也能做到不加鎖,非阻塞併發讀

補充:1.mvcc手段只適用於msyql隔離級別中的讀已提交(read committed)和可重複讀(repeatable read).

2.read uncimmitted由於存在髒讀,即能讀到未提交事務的資料行,所以不適用mvcc.

原因是mvcc的建立版本和刪除版本只要在事務提交後才會產生。

3.序列化由於是會對所涉及到的表加鎖,並非行鎖,自然也就不存在行的版本控制問題。

4.客觀上,我們認為他就是樂觀鎖的一整實現方式,就是每行都有版本號,儲存時根據版本號決定是否成功。但由於mysql的寫操作會加排他鎖,其mvcc並非真正的mvcc,他只是借用mvcc的名號實現了讀的非阻塞而已。

2、什麼是當前讀和快照讀?

在學習mvcc多版本併發控制之前,我們必須先了解一下,什麼是mysql innodb下的當前讀和快照讀?

說白了mvcc就是為了實現讀-寫衝突不加鎖,而這個讀指的就是快照讀, 而非當前讀,當前讀實際上是一種加鎖的操作,是悲觀鎖的實現

3、資料庫併發場景有三種,分別為:

4、mvcc帶來的好處是?

​ 解決(快照)讀-寫衝突的無鎖併發控制,

為事務分配單向增長的時間戳,為每個修改儲存乙個版本,版本與事務時間戳關聯,讀操作唯讀該事務開始前的資料庫的快照。 所以mvcc可以為資料庫解決以下問題

5、小結

總之,mvcc就是因為大牛們,不滿意只讓資料庫採用悲觀鎖這樣效能不佳的形式去解決讀-寫衝突問題,而提出的解決方案,所以在資料庫中,因為有了mvcc,所以我們可以形成兩個組合:

實現原理

主要是依賴記錄中的 3個隱式字段,undo日誌 ,read view 來實現的。

1、隱式字段

每行記錄除了我們自定義的字段外,還有資料庫隱式定義的db_trx_id,db_roll_ptr,db_row_id等字段

如上圖,db_row_id是資料庫預設為該行記錄生成的唯一隱式主鍵,db_trx_id是當前操作該記錄的事務id,而db_roll_ptr是乙個回滾指標,用於配合undo日誌,指向上乙個舊版本

2、undo日誌

undo log主要分為兩種:

purge

對mvcc有幫助的實質是update undo log ,undo log實際上就是存在rollback segment中舊記錄鏈,它的執行流程如下:

一、 比如乙個有個事務插入persion表插入了一條新記錄,記錄如下,name為jerry, age為24歲,隱式主鍵是1,事務id和回滾指標,我們假設為null

二、 現在來了乙個事務1對該記錄的name做出了修改,改為tom

三、 又來了個事務2修改person表的同乙個記錄,將age修改為30歲

從上面,我們就可以看出,不同事務或者相同事務的對同一記錄的修改,會導致該記錄的undo log成為一條記錄版本線性表,既鍊錶,undo log的鏈首就是最新的舊記錄,鏈尾就是最早的舊記錄(當然就像之前說的該undo log的節點可能是會purge執行緒清除掉,向圖中的第一條insert undo log,其實在事務提交之後可能就被刪除丟失了,不過這裡為了演示,所以還放在這裡)

3、read view(讀檢視)

3.1什麼是read view?

事務進行快照讀操作的時候生產的讀檢視(read view),

在該事務執行的快照讀的那一刻,會生成資料庫系統當前的乙個快照,記錄並維護系統當前活躍事務的id(當每個事務開啟時,都會被分配乙個id, 這個id是遞增的,所以最新的事務,id值越大)

所以我們知道 read view主要是用來做可見性判斷的, 即當我們某個事務執行快照讀的時候,對該記錄建立乙個read view讀檢視,把它比作條件用來判斷當前事務能夠看到哪個版本的資料,既可能是當前最新的資料,也有可能是該行記錄的undo log裡面的某個版本的資料。

3.2read view遵循乙個可見性演算法

將要被修改的資料的最新記錄中的db_trx_id(即當前事務id)取出來,與系統當前其他活躍事務的id去對比(由read view維護),如果db_trx_id跟read view的屬性做了某些比較,不符合可見性,那就通過db_roll_ptr回滾指標去取出undo log中的db_trx_id再比較,即遍歷鍊錶的db_trx_id(從鏈首到鏈尾,即從最近的一次修改查起),直到找到滿足特定條件的db_trx_id, 那麼這個db_trx_id所在的舊記錄就是當前事務能看見的最新老版本

那麼這個判斷條件是什麼呢?

如上,它是一段mysql判斷可見性的一段原始碼,即changes_visible方法(大致邏輯),該方法展示了我們拿db_trx_id去跟read view某些屬性進行怎麼樣的比較

3.3三個全域性屬性

trx_list(名字我隨便取的)

乙個數值列表,用來維護read view生成時刻系統正活躍的事務id

up_limit_id

記錄trx_list列表中事務id最小的id

low_limit_id

readview生成時刻系統尚未分配的下乙個事務id,也就是目前已出現過的事務id的最大值+1

4、整體流程1、rr是如何在rc級的基礎上解決不可重複讀的?

當前讀和快照讀在rr級別下的區別:

表1:

表2:

而在表2這裡的順序中,事務b在事務a提交後的快照讀和當前讀都是實時的新資料400,這是為什麼呢?

所以我們知道事務中快照讀的結果是非常依賴該事務首次出現快照讀的地方,即某個事務中首次出現快照讀的地方非常關鍵,它有決定該事務後續快照讀結果的能力

我們這裡測試的是更新,同時刪除和更新也是一樣的,如果事務b的快照讀是在事務a操作之後進行的,事務b的快照讀也是能讀取到最新的資料的

2、rc,rr級別下的innodb快照讀有什麼不同?

正是read view生成時機的不同,從而造成rc,rr級別下快照讀的結果的不同

在rc隔離級別下,是每個快照讀都會生成並獲取最新的read view;

在rr隔離級別下,則是同乙個事務中的第乙個快照讀才會建立read view, 之後的快照讀獲取的都是同乙個read view。

mysql多版本併發控制MVCC

innodb的mvcc是通過在每行記錄的後面儲存兩個隱藏的列來實現的,這兩個列乙個儲存行的建立時間,乙個儲存行的過期時間。但是並不是儲存時間而是儲存版本號,每開始乙個新的事務,版本號會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到每行記錄的版本號進行比較。select innod...

mysql多版本併發控制MVCC

set global transaction isolation level read committed 全域性的 set session transaction isolation level read committed 當前會話 複製 set autocommit 1 自動提交,為0手動提交...

MySQL學習 多版本併發mvcc

mysql中的大多數事務性儲存引擎實現的都不是簡單的行級鎖。基於提公升併發效能的考慮,他們一般實現了多版本併發控制 mvcc 不僅是mysql,包括oracle,postgresql等其他資料庫也實現了mvcc,但各自的實現機制不盡相同,應為mvcc沒有乙個統一的實標準。那麼什麼是mvvc呢 可以認...