MVCC ReadView介紹


對於使用READ UNCOMMITTED隔離級別的事務來說,由於可以讀到未提交事務修改過的記錄,所以直接讀取記錄的最新版本就好了;對於使用SERIALIZABLE隔離級別的事務來說,設計InnoDB的大叔規定使用加鎖的方式來訪問記錄(加鎖是啥我們后續文章中說哈);對於使用READ COMMITTEDREPEATABLE READ隔離級別的事務來說,都必須保證讀到已經提交了的事務修改過的記錄,也就是說假如另一個事務已經修改了記錄但是尚未提交,是不能直接讀取最新版本的記錄的,核心問題就是:需要判斷一下版本鏈中的哪個版本是當前事務可見的。為此,設計InnoDB的大叔提出了一個ReadView的概念,這個ReadView中主要包含4個比較重要的內容:

  • m_ids:表示在生成ReadView時當前系統中活躍的讀寫事務的事務id列表。

  • min_trx_id:表示在生成ReadView時當前系統中活躍的讀寫事務中最小的事務id,也就是m_ids中的最小值。

  • max_trx_id:表示生成ReadView時系統中應該分配給下一個事務的id值。

    小貼士: 注意max_trx_id並不是m_ids中的最大值,事務id是遞增分配的。比方說現在有id為1,2,3這三個事務,之后id為3的事務提交了。那么一個新的讀事務在生成ReadView時,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。

  • creator_trx_id:表示生成該ReadView的事務的事務id

    小貼士: 我們前邊說過,只有在對表中的記錄做改動時(執行INSERT、DELETE、UPDATE這些語句時)才會為事務分配事務id,否則在一個只讀事務中的事務id值都默認為0。

有了這個ReadView,這樣在訪問某條記錄時,只需要按照下邊的步驟判斷記錄的某個版本是否可見:

  • 如果被訪問版本的trx_id屬性值與ReadView中的creator_trx_id值相同,意味着當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值小於ReadView中的min_trx_id值,表明生成該版本的事務在當前事務生成ReadView前已經提交,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值大於或等於ReadView中的max_trx_id值,表明生成該版本的事務在當前事務生成ReadView后才開啟,所以該版本不可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值在ReadViewmin_trx_idmax_trx_id之間,那就需要判斷一下trx_id屬性值是不是在m_ids列表中,如果在,說明創建ReadView時生成該版本的事務還是活躍的,該版本不可以被訪問;如果不在,說明創建ReadView時生成該版本的事務已經被提交,該版本可以被訪問。

如果某個版本的數據對當前事務不可見的話,那就順着版本鏈找到下一個版本的數據,繼續按照上邊的步驟判斷可見性,依此類推,直到版本鏈中的最后一個版本。如果最后一個版本也不可見的話,那么就意味着該條記錄對該事務完全不可見,查詢結果就不包含該記錄。

MySQL中,READ COMMITTEDREPEATABLE READ隔離級別的的一個非常大的區別就是它們生成ReadView的時機不同。

  • READ COMMITTED —— 每次讀取數據前都生成一個ReadView

  • REPEATABLE READ —— 在第一次讀取數據時生成一個ReadView


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM