閱讀46 返回首頁    go 技術社區[雲棲]


MySQL鎖係列(六)之 MVCC

agenda

我們能學到什麼

  • 什麼是MVCC

  • MVCC能解決什麼問題

  • MVCC的實現原理

一、什麼是MVCC

  • 名詞解釋
英文名:Multi Version Concurrency Control
中文名:多版本一致性控製
  • 應用場景
  1. 大家有沒有這樣的疑問,線上的表一直被更新,可是為什麼還可以去select呢?
  2. 我的更新事務還沒有提交,為什麼另外一個事務可以讀到數據呢?
  3. 我的更新事務已經提交,另一個事務又是怎麼選擇數據返回給用戶呢?

二、MVCC能解決什麼問題

  • 解決的問題
1. snapshot查詢不會加鎖,讀和讀,讀和寫之間互不影響,提高數據庫的並發能力
2. 隔離級別的實現

三、MVCC的實現原理

3.1 row的記錄格式

記住這個格式,很重要

innodb_locks_mvcc_1

3.2 row 和 undo

innodb_locks_MVCC_2

3.3 readview

innodb_locks_MVCC_3

3.4 可見性判斷

  • 實現原理
readview = 活躍事務列表
readview(RR): 事務開始時產生readview
readview(RC): 每條語句都會產生readview

如何判斷可見性:

假設:活躍事務為(3,4,5,6)=readview,當前事務id號為10,做了修改這條記錄 , 那麼這條記錄上的db_trx_id=10

流程如下:

當前事務(trxid=10)拿著剛剛產生的readview =(3[active_trx_min],4,5,6【active_trx_max】)去查看記錄,


1.如果row上的db_trx_id in (活躍事務列表),那麼說明此記錄還未提交,這條記錄對於此事務不可見.需要調用上一個undo,用同樣的判斷標準過濾,循環
2.如果row上的db_trx_id < 活躍事務列表最小值,那麼說明已經提交,這條記錄對於此事務可見
3.如果row上的db_trx_id > 活躍事務列表最大值, 那麼說明該記錄在當前事務之後提交,這條記錄對於此事務不可見.需要調用上一個undo,用同樣的判斷標準過濾,循環


這裏有個問題: 當前事務id更新後,會鎖住該記錄並更新db_trx_id=10,那麼該記錄上的trx_id肯定是<=當前事務id(10)的,那既然這樣,怎麼會產生db_trx_id > 活躍事務列表最大值呢?

原因:因為當前事務不僅僅是讀取這條被鎖住的記錄,可能還需要讀取其他記錄(這些記錄當然可能被其他更靠後的事務id更新了),那麼這時候其他記錄上的db_trx_id>=10就很正常不過了。

創建readview的位置,不是begin的那個位置,而是begin後麵的SQL語句的位置。(換句話說:就是begin的時候不會分配事務id,隻有執行了sql之後才會分配事務id)
如果你想在開啟transaction的時候就產生readview,分配事務id,那麼可以這樣操作:start transaction with consistent snapshot

percona 中可以有這樣的信息,官方沒有: Trx read view will not see trx with id >= 413  , sees < 411
  • 案例剖析 innodb_locks_MVCC_4

最後更新:2017-06-17 08:32:27

  上一篇:go  王者
  下一篇:go  6月16日雲棲精選夜讀:數據庫分布式架構巧設計,水平拆分不再難