天天看點

MySQL官方文檔14.3 InnoDB多版本控制

原文位址:https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html

14.3 InnoDB多版本控制

InnoDB是一個多版本的存儲引擎,它儲存着有關行修改的舊版本資訊,支援事務特性,例如并發和復原,此資訊存儲在稱為復原段(oracle的一個類似的資料結構)的資料結構的表空間中,InnoDB使用復原段中的資訊來執行一個事務復原需要的撤銷操作,它還使用這些資訊為一個一緻性讀取操作建立行的早期版本。

實際上,InnoDB為每個存儲在資料庫中的行都添加了三個字段,一個6位元組的DB_TRX_ID字段表示最後一次插入或者更新行的事務操作的事務辨別,同樣的,一個删除操作被看作為一個内部地更新操作在行的特殊位置被标記為已删除;每個行同樣包含一個7位元組的DB_ROLL_PTR字段稱作為復原指針,復原指針指向一個被寫入到復原段中的撤銷日志記錄,如果行被更新了,撤銷日志記錄包含在更新該行之前重建該行内容所必需的資訊;一個6位元組的DB_ROW_ID字段包含一個在有新行插入時單調遞增的行ID,如果InnoDB自動生成聚簇索引,索引就會包含行ID的值,否則,DB_ROW_ID列不會出現在任何索引中。

復原段中的撤銷日志分為插入和更新撤銷日志,插入撤銷日志僅僅在事務復原時需要,事務一送出就可以丢棄,更新撤銷日志也用于一緻性讀取,但是隻有在InnoDB沒有配置設定快照的情況下,才可以丢棄這些快照,在一緻性讀取中可能需要更新撤銷日志中的資訊來建構資料庫行的早期版本。

定期送出你的事務,包括那些隻發生一緻性讀取操作的事務,否則,InnoDB不能從更新撤銷日志中丢棄資料,并且復原段可能變得太大,填滿你的表空間。

復原段中的撤銷日志記錄的實體大小通常小于相應的插入或更新的行,您可以使用此資訊來計算復原段所需的空間。

在InnoDB多版本方案中,當您使用SQL語句删除行時,行不會立即從資料庫中實體删除,InnoDB隻在丢棄為删除而寫入的更新撤銷日志記錄時才實體删除相應的行及其索引記錄,這個删除操作被稱為清除,并且非常快,通常與删除SQL語句的時間順序相同。

如果你在表中以相同的速率插入和删除小批量的行,清除線程可能滞後開始,并且由于所有“死”行,表可能變得越來越大,使所有的東西都是磁盤綁定的并且非常慢,在這種情況下,限制新的行操作,并通過調整innodb_max_purge_lag系統變量向清除線程配置設定更多資源。有關更多資訊,請參見第14.14節“InnoDB啟動選項和系統變量”。

多版本和二級索引

InnoDB多版本并發控制(MVCC)将二級索引視為與聚簇索引不同,聚簇索引中的記錄就地更新,并且他們的隐藏系統列指向可以重建記錄的早期版本的撤消日志條目,與聚簇索引記錄不同,二級索引記錄不包含隐藏的系統列,也不就地更新。

當一個二級索引被更新後,舊的二級索引記錄将被标記為删除,新的記錄被插入,并且被标記為删除的記錄最終會被清除,當二級索引記錄被标記為删除或者二級索引頁被一個較新的事務更新時,InnoDB查找聚簇索引中的資料庫記錄,在聚簇索引中,檢查記錄的DB_TRX_ID,如果記錄在讀取事務啟動後被修改,則從撤消日志中檢索正确版本的記錄。

如果二級索引記錄被标記為删除或者二級索引頁被較新的事務更新,則不使用覆寫索引技術,InnoDB不是從索引結構中傳回值,而是在聚簇索引中查找記錄。

但是,如果啟用索引條件下推(ICP)優化,并且僅可以使用索引中的字段來評估WHERE條件的部分内容,MySQL伺服器仍将WHERE條件的這一部分向下推送到使用索引進行評估的存儲引擎,如果找不到比對的記錄,則避免聚簇索引查找,如果找到比對的記錄,即使在删除标記的記錄中,InnoDB也會在聚簇索引中查找記錄。

繼續閱讀