本文轉自互聯網
MVCC是multiversion concurrency control的縮寫,提供MySQL事物隔離級別下無鎖讀,例如一個事物在執行update等修改數據的sql,並未提交時其他事物進行數據讀取是不影響的,而且讀取內容為數據變更之前的數據。
mvcc多本版快照由innodb的rollback segment構照的,一個sql進行查找數據當查找到某一個數據需要到回滾段中查找數據時,就會根據當前頁上行數據的一個指針到回滾段中查找對應數據,在innodb的表主鍵中都會存在三個隱藏的字段:
DB_TRX_ID:該字段存儲最後一個修改該行數據的事務ID,占用6byte的空間,MySQL的delete操作是標記刪除,所以對應行數據的該字段就為一個刪除標記。
DB_ROLL_PTR:該字段就記錄執行roll segment的指針信息,當事務需要rollback時就通過該字段尋找記錄重新構照行數據,該字段占用7byte空間。
DB_ROW_ID:記錄每個行ID,該ID值為單調遞增型整數,在innodb表指定了主鍵之後DB_ROW_ID存在於主鍵索引上,如果無主鍵該值就不會存在,占用6byte空間。
在一個sql進行查詢時,讀取到一行數據的DB_TRX_ID值和自己事物ID的對比,假如隔離級別為MySQL的默認級別,就只讀取該ID值小於本身事物ID的數據,其余數據就需要通過DB_ROLL_PTR的信息到回滾段中讀取。MVCC是否起到相應的作用需取決於數據庫隔離級別的配置。
在insert和update、delete的操作是有區別的,一個insert語句插入數據再rollback就是直接對undo log的刪除,網上關於這部分的教程比較少,因為他並不會影響其他事物的讀取操作,而update、delete操作是在原有數據做更改,可能有其他事物在對該行數據做讀取操作,所以update、delete產生的undo log數據是由內部線程自動清理,在該數據無任何事務在使用時清理掉,所以在undo log中insert和update、delete產生的數據存於不同位置。
上面說了數據的update、delete、insert操作,都會根據主鍵上的隱藏列來判斷和查找,但是輔助索引並不存在隱藏列,輔助索引就是有索引列和主鍵列組成的一個小表,這該怎麼判斷呢?輔助索引區別在於假如是一個update操作步驟為:
1、標記刪除原紀錄
2、插入新紀錄
3、對應主鍵做上面的隱藏字段修改,行數據更新,原行數據移入回滾段
一個查詢語句在利用輔助索引進行查找時,發現有個標記刪除或者有新數據就會到主鍵掃描對應的DB_TRX_ID值對比當前事物ID大小,是否利用DB_ROLL_PTR進行讀取數據。輔助索引的delete、insert也是類似,只是一個沒有新紀錄,一個沒有標記刪除記錄。