InnoDB 是一個數據多版本的存儲引擎,它會保持它修改的數據的舊版本數據以此來支持事務特性,好比並發操做和事務的回滾。這些舊版本數據存儲在一個叫作rollback segment的數據結構中(回滾段),當事務回滾的時候,Innodb會使用回滾段的數據來執行事務的撤銷操做,也會使用這些老版本的數據來作舊版本的一致性讀操做(可重複讀的隔離級別下須要用到)。html
在Innodb內部會增長三個字段存儲相關信息,6個字節的 DB_TRX_ID 字段標識插入或者更新該字段的最後一個事務的事務ID,刪除操做在內部是視爲更新操做,在行上標記爲已刪除,每一行包含一個7個字節的DB_ROLL_PTR字段,也叫着行指針,行指針指向undo log在回滾段(rollback segment)中的位置, 若是該行被更新了,undo log 包含了該行被更新前的必要的重建行的信息。6個字節的 DB_ROW_ID 字段,這個字段隨着記錄的插入而單調遞增,若是Innodb自動生成一個聚簇索引(沒有顯示指定主鍵),那這個索引包含了db_row_id字段,不然,db_row_id 這個列不會出如今任何索引中。mysql
回滾段中的undo log 分紅inser 和update 兩類,insert undo log 只在事務回滾中被須要,而且能夠在事務提交時丟棄這類日誌。update undo log被用於一致性讀,只有當沒有未提交的事務時才能被丟棄,Innodb爲事務分配了一個快照在一致性讀時,它須要update undo log的信息來構建數據的舊的版本數據。sql
按期提交事務,也包含那些一致讀的事務,不然innodb由於不能丟棄回滾段中的undo log會致使回滾段變得很大以至於佔滿表空間。數據庫
回滾段中的undo log記錄大小通常小於它相應行的大小,你能夠基於這個來計算你須要的回滾段大小。數據結構
Innodb多版本模式下,當你使用SQL語句刪除行時它不會馬上從數據庫物理刪除數據,Innodb只會在丟棄相應的undo log時纔會物理刪除數據和索引數據,這個移除操做在Innodb中叫着purge,這個動做很是迅速,一般跟SQL的執行順序一致。併發
若是插入和刪除操做以差很少相同的速度進行,purge 線程會有延遲,表會變得愈來愈大由於表中的"dead" 行,這會致使性能被磁盤IO限制,在這種場景下,經過調整系統參數 innodb_max_purge_lag
來分配跟多的資源給purge線程。性能
多本版和二級索引線程
Innodb多版本併發控制對二級索引的處理不一樣於聚簇索引(primary key),聚簇索引中的記錄會被就地更新,他們指向undo log的隱藏系統列能夠構建舊版本數據,不一樣於聚簇索引,二級索引記錄不包含隱藏系統列,不能被就地更新。翻譯
當二級索引被更新的時候,老的記錄被標記刪除,插入一條新記錄,標記刪除的數據最終被移除,當二級索引記錄標記刪除或者二級索引的頁被一個新事務更新,Innodb在聚簇索引中找到這些記錄,在聚簇索引中,檢查這些行的 DB_TRX_ID,若是這些行在當前事務啓動以後被更新了,那麼就從undo log中獲取老版本的數據。 指針
當二級索引記錄被標記刪除或者二級索引的頁被一個新事務更新,索引覆蓋技術再也不適用,不一樣於直接從索引返回數據,Innodb會從聚簇索引中尋找數據。
(翻譯至MySQL官方文檔)