InnoDB是一個多版本(MVCC)的存儲引擎。
它保留有關更改行的舊版本的信息,以支持事務性功能,如并發和回滾。
這些信息存儲在稱為回滾段的數據結構中的Undo表空間中。
參見“Undo表空間”。
InnoDB使用回滾段(rollback segment.)中的信息來執行事務回滾中所需的撤消操作
它還使用這些信息構建行的早期版本,以實現一致的讀取。
參見“無鎖的一致讀”。
在內部,InnoDB向數據庫中存儲的每一行添加三個字段:
6字節DB_TRX_ID字段
指示插入或更新該行的最后一個事務的事務標識符。此外,刪除在內部被視為更新,行中的一個特殊位被設置為將其標記為已刪除。
7字節DB_ROLL_PTR字段
回滾指針。滾動指針指向寫入回滾段的撤消日志記錄。如果該行已更新,則撤消日志記錄包含在該行更新之前重新生成該行內容所需的信息。
6字節DB_ROW_ID字段
包含一個行ID,該行ID隨著新行的插入而單調增加。如果InnoDB自動生成聚集索引,則該索引包含行ID值。否則,DB_ROW_ID列不會出現在任何索引中。
回滾段中的撤消日志分為插入和更新Undolog。插入Undolog僅在事務回滾中需要,并且可以在事務提交后立即丟棄。
更新Undolog也用于一致讀,但只有在不存在InnoDB已為其分配快照的事務之后,才能丟棄這些日志。
在一致讀中,快照可能需要更新Undolog中的信息來構建數據庫行的早期版本。
有關Undolog的更多信息,請參閱“Undolog”。
【MySQL精通之路】InnoDB(6)-磁盤結構(5)-Undolog-CSDN博客
建議您定期提交事務,包括只發出一致讀的事務。
否則,InnoDB無法丟棄更新Undolog中的數據,回滾段可能會過大。
從而填滿其所在的Undolog表空間。
有關管理Undolog的信息,請參閱“Undolog表空間”。
回滾段中撤消日志記錄的物理大小通常小于相應的插入或更新行。您可以使用這些信息來計算回滾段所需的空間。
在InnoDB多版本控制(MVCC)方案中,當您使用SQL語句刪除一行時,它不會立即從數據庫中物理刪除。
當InnoDB丟棄為刪除而寫的更新Undolog記錄時,它只物理地刪除相應的行及其索引記錄。此刪除操作被稱為清除,而且速度非常快,通常與執行刪除的SQL語句所花費的時間順序相同。
如果在表中以大致相同的速率小批量插入和刪除行,則清除線程可能會開始滯后,并且由于所有“死行”(dead rows),表可能會變得越來越大,從而使所有內容都綁定到磁盤,并且速度非常慢。
在這種情況下,通過調整innodb_max_purge_lag系統變量來限制新行操作,并為清除線程分配更多資源。
有關更多信息,請參閱“清除配置”。
2.多版本控制和輔助索引
InnoDB多版本并發控制(MVCC)對待二級索引的方式不同于聚集索引。
聚集索引中的記錄會立即更新,其隱藏的系統列指向撤消日志項,可以從中重建早期版本的記錄
與聚集索引記錄不同,輔助索引記錄不包含隱藏的系統列,也不會立即更新。
更新輔助索引列時,會對舊的輔助索引記錄進行刪除標記,插入新記錄,并最終清除帶有刪除標記的記錄。
當二級索引記錄被刪除標記或二級索引頁面被更新的事務更新時,InnoDB會在聚集索引中查找數據庫記錄。
在聚集索引中,檢查記錄的DB_TRX_ID,如果在啟動讀取事務后修改了記錄,則從撤消日志中檢索記錄的正確版本。
如果二級索引記錄被標記為刪除,或者二級索引頁由較新的事務更新,則不使用覆蓋索引技術。InnoDB不是從索引結構中返回值,而是在聚集索引中查找記錄。
但是,如果啟用了索引條件下推(ICP)優化,并且只能使用索引中的字段來評估WHERE條件的部分,MySQL服務器仍然會將WHERE條件的這一部分下推到使用索引進行評估的存儲引擎。
如果找不到匹配的記錄,將避免進行聚集索引查找。
如果找到匹配的記錄,即使在已刪除標記的記錄中,InnoDB也會在聚集索引中查找該記錄。