MySQL MVCC機制


本文同時發表在https://github.com/zhangyachen/zhangyachen.github.io/issues/68

行結構

每一行額外包含三個隱藏字段:

  • DB_TRX_ID:事務ID。行的創建時間和刪除時間記錄的就是此值。
  • DB_ROLL_PTR:指向當前記錄項的undo信息。
  • DB_ROW_ID::隨着新行插入單調遞增的一個字段。當由innodb自動產生聚集索引時,聚集索引包括這個DB_ROW_ID的值,不然的話聚集索引中不包括這個值。
  • 在insert操作時,創建時間 = DB_ROW_ID,這時,“刪除時間 ”是未定義的。
  • 在update操作時,復制新增行的“創建時間”=DB_ROW_ID,刪除時間未定義,舊數據行“創建時間”不變,刪除時間=該事務的DB_ROW_ID。
  • 在delete操作時,相應數據行的“創建時間”不變,刪除時間 = 該事務的DB_ROW_ID。
  • select操作對兩者都不修改,只讀相應的數據。

Read View

    dulint    low_limit_id;    /* 事務號 >= low_limit_id的記錄,對於當前Read View都是不可見的 */

    dulint    up_limit_id;    /* 事務號 < up_limit_id ,對於當前Read View都是可見的 */

    ulint    n_trx_ids;    /* Number of cells in the trx_ids array */

    dulint*    trx_ids;    /* Additional trx ids which the read should

                not see: typically, these are the active

                transactions at the time when the read is

                serialized, except the reading transaction

                itself; the trx ids in this array are in a

                descending order */

dulint    creator_trx_id;    /* trx id of creating transaction, or

                (0, 0) used in purge */

關於low_limit_id,up_limit_id的理解:
up_limit_id:當前已經提交的事務號 + 1,事務號 < up_limit_id ,對於當前Read View都是可見的。理解起來就是創建Read View視圖的時候,之前已經提交的事務對於該事務肯定是可見的。
low_limit_id:當前最大的事務號 + 1,事務號 >= low_limit_id,對於當前Read View都是不可見的。理解起來就是在創建Read View視圖之后創建的事務對於該事務肯定是不可見的。

另外,trx_ids為活躍事務id列表,即Read View初始化時當前未提交的事務列表。所以當進行RR讀的時候,trx_ids中的事務對於本事務是不可見的(除了自身事務,自身事務對於表的修改對於自己當然是可見的)。理解起來就是創建RV時,將當前活躍事務ID記錄下來,后續即使他們提交對於本事務也是不可見的。

example

步驟 1 2 3
begin
begin
insert into test(score) values(1607); 假設此時事務號21
insert into test(score) values(1607); 此時事務號22
image 此時創建讀視圖,up_limit_id = 21, low_limit_id = 23 活躍事務列表為(21,22)
insert into test(score) values(1620); 事務號為23
insert into test(score) values(1621); 事務號為24
insert into test(score) values(1622); 事務號為25
select * from test; 此時的up_limit_id 為21,low_limit_id 為26,活躍事務列表為(21,22),故21,22在活躍事務列表不可見 image
select * from test; 此時low_limit_id為26,up_limit_id 為21,活躍事務列表是(21,22) 22本事務自身可見。21的在活躍事務列表不可見。23,24不在活躍事務列表,可見 image
十一 select * from test; 事務內readview不變,low_limit_id = 23,up_limit_id = 21,活躍事務列表 (21,22)。故21自身可見,22在活躍事務列表不可見。>=23的都不可見 image

注意的幾點:

  • Read View視圖是在進行RR讀之前創建的,而不是在事務剛begin時創建的。如果Read View視圖是在事務剛begin時創建的,那么在步驟四中事務22的Read View就定下來了(up_limit_id = 21,low_limit_id = 23),那么在步驟十中就看不到3中提交的數據了,因為事務號23,24,25大於等於事務22.low_limit_id
  • 事務內Read View一旦創建就不變化了。
  • 在第十步中按我之前的理解,3中insert的數據是在2中begin之后插入的,按理說2是看不到3中insert插入的數據的。但是事務保證的是兩次select的數據是一致的,所以Read View是在第一次select時創建的,所以3中insert的數據是在2中可以看到。

參考資料:http://hedengcheng.com/?p=148


免責聲明!

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



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