java面試一日一題:講對mysql的MVCC的理解

迷茫中守候發表於2021-04-15

問題:請講下對mysql中MVCC的理解

分析:這個問題要回答的是對MVCC的理解,以及MVCC解決了什麼問題這幾個方面入手。

回答要點:

主要從以下幾點去考慮,

1、什麼是MVCC?

2、MVCC用來解決什麼問題?

3、MVCC是怎麼實現的?

 

所謂MVCC,在mysql中指的是multi version concurrency control,即多版本併發控制。多版本比較好理解就是有多個版本,那麼是指的什麼有多個版本,這裡指的是資料行,mysql中的資料行有多個版本,再看後面的併發控制,即對資料的行的讀取和更新要併發控制,併發控制的目的是為了多執行緒下的資料安全,就像在java環境下的多執行緒安全,這裡並不是指執行緒安全,而是指多個執行緒下的資料隔離級別。

MVCC只有在讀已提交和可重複讀兩種隔離級別下才有效。我們都知道在讀已提交隔離級別下解決了髒讀,但存在不可重複讀及幻讀的情況,在可重複讀隔離級別下解決了不可重複讀和幻讀(如何解決的下篇文章分享),下面就看下在這兩個隔離級別下MVCC是如何其作用的。

MVCC的實現是通過undo log和read view來實現的

在innodb引擎下的表,每個資料行都有隱藏的兩列,一列是trx_id,也就是更新(insert、update、delete)這條記錄的事務ID;一列是roll_pointer,指向上次修改的指標,如果是新增的則為null;如果不存在主鍵的話,還會有第三列row_id,在沒有主鍵的情況下預設生成的主鍵;

我們都知道在mysql的事務日誌中有redo log和undo log,redo log記錄的是真實改變的值,而undo log記錄的是和操作相反的操作,由於一條記錄可能會被修改多次,這些修改連在一起就形成了一個版本鏈,這個版本鏈就是MVCC實現的基礎。

如下就是一個版本鏈

其中最後兩列一個是trx_id,一個是roll_pointer。有了版本鏈,還有一個read view,看這是什麼概念,翻譯過來叫一致性檢視,一致性檢視中有以下幾個屬性比較重要,

m_ids,在生成read view時當前活躍的讀寫事務的列表

min_trx_id,m_ids中最小的

max_trx_id,m_ids中最大的+1

版本鏈中的trx_id是否對當前事務可見通過以下的規則進行判斷,

trx_id<min_trx_id 表示資料中的事務ID比當前活躍的事務id最小的還小,代表該記錄在生成readview的時候已經提交,那麼是可見的;

trx_id>=max_trx_id 表示資料中的事務ID比當前活躍的事務id最大的還大,代表該記錄在生成readview後提交的,那麼是不可見的;

min_trx_id<=trx_id<max_trx_id 當trx_id在m_ids中表示,該事務還未提交,那麼是不可見的;當trx_id不在m_ids中,說明已經提交了,那麼是可見的;

如果某個版本的資料對當前事務是不可見的,那麼就要順著版本鏈繼續查詢下個版本,直到找到可見的版本。

 

那麼在讀已提交和可重複讀下是如何實現的,在讀已提交下,是每次select都會生成read view,所以可以讀到提交的資料;在可重複讀隔離級別下,是在第一次select的時候生成read view,以後的select都是使用第一次生成的read view,所以解決了不可重複讀。

 

相關文章