該文章是《innodb的mvcc簡介》中的細節作出解釋。
在mvcc出現之前的資料庫,為了實現一致性讀,如sqlserver,db2均採用鎖定讀技術,寫操作往往會阻塞讀操作,導致資料庫併發效能不高。
oracle與postgre相繼推出自己的多版本併發控制技術,這一技術的核心是在發生讀寫衝突時候,讀操作不再被寫操作阻塞,而是直接讀取寫操作所在行的前乙個版本。如何構建歷史版本,oracle與postgre分別採用了兩種思路來實現。
postgre採用的方式:更新的記錄生成新記錄與舊記錄,均儲存在資料頁中,沒有回滾段和undo日誌記錄
oracle採用回滾段與undo日誌記錄,undo日誌記錄僅僅儲存更新前的修改的必要資訊,結合現有記錄就能構建歷史版本
postge採用的方式存在的問題是,如果更新較多,且頻繁, 資料頁空間膨脹得很厲害。由於不支援原位更新(update in place), 攜帶刪除標記的記錄相對也多,空間**的程序對系統影響也很大。
innodb採用的方式與oracle類似,採用回滾記錄的方式構造歷史記錄。
在前面的文章講過,聚集索引的行記錄至少有兩個隱藏列,db_trx_id 與 db_roll_ptr,其含義已經在《innodb的mvcc簡介》中講過。
其中db_trx_id用行對事務可見性判斷,db_roll_ptr作為指向回滾記錄的指標,其結構如下
至於undo的表空間,undo頁記錄是怎麼儲存的,這裡不再贅述,講mvcc原理只需要知道能通過rollptr找到undo的記錄。
update 的undo記錄的內容通常有:
《innodb的mvcc簡介》一文講過,進行讀操作的事務,檢查行中的db_trx_id來決定是否讀取歷史版本。
而這個檢查過程,則是通過行中的db_trx_id所表示的事務id,與讀操作事務readview結構進行比較,決定當前行是否可見,如果可見,返回當前行,否則要讀取undo記錄,構造歷史行記錄。
readview來判斷行是否可見,不是很容易理解。要理解這個過程,先要明確:
那麼可以知道,trx_id小的事務,進行寫操作必定早於trx_id大的事務進行的寫操作。乙個事務的trx_no必定比它的trx_id大。
readview中有如下字段:
以上的文字不是很好理解,可以用如下式子表示,這樣方便理解。
這裡有三部分
如下示例:
黃色部分表示乙個唯讀事務,沒有trx_id, 虛線部分表示讀操作發生的時刻。無論隔離級是讀提交還是可重複讀,正在修改還沒有提交的事務的資料都不允許讀到(否則就是髒讀隔離級了)。 那麼,當時正在執行的事務有t4與t6,已經提交的事務t1,t2,t3,t5, 這些事務的資料都是可見的。innodb構造的readview為
發現行資料不可見之後,如何構造歷史版本,《innodb的mvcc簡介》一文已經講得很清楚,這裡就不講了。
可以認為,乙個readview相當於乙個快照點,讀提交隔離級,意味著事務中多次讀操作,每一次讀操作,都要讀乙個新的快照點,也就要重新構造乙個readview, 而可重複讀,意味著多次讀操作,都應該讀同乙個快照點,所以要重用最開始的readview。
purge流程比較複雜,要講清楚需要另開乙個專題才能講明白。這裡僅僅將它的設計原則。
purge 也有乙個readview,是從事務系統複製過來最古老的readview。purge的readview可見的記錄,均可認為undo日誌可以清除,最古老的事務更改的資料,對於purge來說應該是不可見的,所以需要將m_creator_trx_id重新放入到readview的活躍列表中。
實際上purge僅僅purge 小於最古老的readview的m_low_limit_no的undo記錄。所以要及時提交事務,如果事務哪怕是唯讀事務長期不提交,會阻止purge的清空資料頁攜帶delete_mark的記錄,以及回滾空間的**。
purge有兩個步驟,乙個步驟是清理資料頁中攜帶delete mark的記錄(purge),如果乙個undo頁所有的undo記錄都做了purge,則會**該undo頁,如果乙個檔案所有頁均**完,滿足乙個閾值條件(innodb_max_undo_log_size與innodb_undo_log_truncate控制)就會收縮檔案大小(truncate)
mvcc原理 MVCC 原理
mvcc 原理 簡單說,讀了一條未提交的資料 乙個事務讀取了另外乙個事務修改後記錄 強調的是 update 和delete 只需要鎖住滿足條件的記錄即可 乙個事務讀取了另外乙個事務插入的資料,強調的是 insert 要鎖住滿足條件及相近的記錄。mysql 中預設的隔離級別是可重複讀,可解決髒讀和不可...
innoDB的MVCC實現方式
innodb的mvcc是通過在每行記錄後面儲存兩個隱藏的列來實現。乙個儲存行的建立時間,乙個儲存行的過期時間,儲存的值為系統版本號。每開啟乙個新的事務,系統版本號都會自動增加。在repeatable read隔離級別下,mvcc的具體操作 insert delete update 儲存這兩個額外系統...
簡述 InnoDB 對 MVCC 的實現
分為兩個要點簡述 要點一 行記錄的歷史版本是什麼樣子的?innodb 將行記錄及其歷史行記錄通過隱藏字段 data roll ptr 鏈成乙個鍊錶。歷史行記錄其實就是 undo log,放在共享表空間的 undo 段。要點二 當前事務進行快照讀時,如何選擇歷史版本?每個行記錄及其歷史行記錄都有乙個隱...