InnoDB
是一種多版本儲存引擎。它會保留有關已變更列的舊版本資訊,以支援交易功能,例如並行和回滾。此資訊會儲存在復原表空間中,在一個稱為回滾區段的資料結構中。請參閱第 17.6.3.4 節,「復原表空間」。InnoDB
使用回滾區段中的資訊來執行交易回滾中需要的回復操作。它還使用該資訊來為一致性讀取建立較早版本的列。請參閱第 17.7.2.3 節,「一致性非鎖定讀取」。
在內部,InnoDB
會將三個欄位新增到資料庫中儲存的每一列
一個 6 位元組的
DB_TRX_ID
欄位,表示最後插入或更新該列的交易的交易識別碼。此外,刪除在內部被視為更新,其中會設定列中的一個特殊位元以將其標記為已刪除。一個 7 位元組的
DB_ROLL_PTR
欄位,稱為回滾指標。回滾指標指向寫入回滾區段的復原日誌記錄。如果列已更新,則復原日誌記錄包含重建更新前列內容所需的資訊。一個 6 位元組的
DB_ROW_ID
欄位,包含一個隨著插入新列而單調增加的列 ID。如果InnoDB
自動產生叢集索引,則索引會包含列 ID 值。否則,DB_ROW_ID
欄位不會出現在任何索引中。
回滾區段中的復原日誌會分為插入和更新復原日誌。插入復原日誌僅在交易回滾中需要,並且可以在交易提交後立即丟棄。更新復原日誌也用於一致性讀取,但只有在不存在任何交易時,才能丟棄它們,InnoDB
為該交易指派了一個快照,該快照在一致性讀取中可能需要更新復原日誌中的資訊來建立較早版本的資料庫列。有關復原日誌的更多資訊,請參閱第 17.6.6 節,「復原日誌」。
建議您定期提交交易,包括僅發出一致性讀取的交易。否則,InnoDB
無法從更新復原日誌中丟棄資料,並且回滾區段可能會變得太大,填滿其所在的復原表空間。有關管理復原表空間的資訊,請參閱第 17.6.3.4 節,「復原表空間」。
回滾區段中復原日誌記錄的實體大小通常小於對應的插入或更新列。您可以使用此資訊來計算回滾區段所需的空間。
在 InnoDB
多版本機制中,當您使用 SQL 語句刪除資料列時,該資料列並不會立即從資料庫中實際移除。InnoDB
只有在捨棄為刪除操作所寫入的更新還原日誌記錄時,才會實際移除對應的資料列及其索引記錄。這種移除操作稱為清除 (purge),它相當快速,通常花費的時間與執行刪除操作的 SQL 語句的時間差不多。
如果您在表格中以小批量且大致相同的速率插入和刪除資料列,清除執行緒可能會開始落後,且表格可能會因為所有 「已失效」的資料列而變得越來越大,導致所有操作都受限於磁碟,並且非常緩慢。在這種情況下,請節流新的資料列操作,並透過調整 innodb_max_purge_lag
系統變數,為清除執行緒分配更多資源。如需更多資訊,請參閱 第 17.8.9 節「清除配置」。
InnoDB
多版本並行控制 (MVCC) 對於次要索引的處理方式與叢集索引不同。叢集索引中的記錄會就地更新,它們的隱藏系統欄位會指向還原日誌項目,可以從中重建較早版本的記錄。與叢集索引記錄不同,次要索引記錄不包含隱藏系統欄位,也不會就地更新。
當次要索引欄位被更新時,舊的次要索引記錄會被標記為刪除,新的記錄會被插入,而標記為刪除的記錄最終會被清除。當次要索引記錄被標記為刪除,或次要索引頁面被較新的交易更新時,InnoDB
會在叢集索引中查找資料庫記錄。在叢集索引中,會檢查記錄的 DB_TRX_ID
,如果記錄是在讀取交易啟動後被修改,則會從還原日誌中檢索正確版本的記錄。
如果次要索引記錄被標記為刪除,或次要索引頁面被較新的交易更新,則不會使用覆蓋索引技術。 InnoDB
不會從索引結構傳回值,而是會在叢集索引中查找記錄。
但是,如果啟用 索引條件下推 (ICP) 優化,且 WHERE
條件的部分可以使用索引中的欄位進行評估,MySQL 伺服器仍然會將 WHERE
條件的這一部分下推到儲存引擎,在該處使用索引進行評估。如果未找到符合的記錄,則會避免叢集索引查找。如果找到符合的記錄,即使是在標記為刪除的記錄中,InnoDB
也會在叢集索引中查找記錄。