【Mysql-InnoDB系列】一 InnoDB的ACID模型

InnoDB的ACID

ACID模型是一些列數據庫設計原則的集合,旨在提升可靠性,這對商業數據和關鍵應用是至關重要的。MySQL包含諸多組件,例如嚴格遵循ACID模型的InnoDB存儲引擎,以保障數據不會因爲軟件崩潰和硬件故障,而導致數據損壞和結果失真。當依賴ACID一致性特性時,你不需要自己再造輪子來進行校驗和故障恢復機制。如果你有額外的軟件保護措施,超可靠的硬件,或者應用可容忍小部分的數據丟失或不一致,你可以調整MySQL配置,通過犧牲一些ACID的可靠性來獲得更高的性能或吞吐量。

InnoDB的多版本(MVCC)

InnoDB是多版本支持的存儲引擎:它爲發生變化的行保存了舊版本信息,來支持併發和回滾的事務特性。信息存儲在表空間,一個稱爲回滾段-roolback segment(在Oracle使用類似的數據結構之後)的數據結構。InnoDB使用回滾段中的信息來執行一個事務回滾之後的undo操作。這個信息也同樣被用來在一致讀場景下建立行數據的早期版本。

InnoDB爲在數據庫中存儲的每行數據增加了3個字段。

1、一個6比特的DB_TRX_ID字段,代表上一個事務的插入/更新行操作的事務標識符。刪除在內部被視爲更新,行中的特殊位被設置爲將其標記爲已刪除。

2、一個7比特的DB_ROLL_PTR字段,稱爲回滾指針。回滾指針指向寫入回滾段的一條undo日誌記錄。如果行被更新,那麼包含這個信息的undo日誌記錄,在更新前必須重新生成行記錄。

3、一個6比特的DB_ROW_ID字段,插入新行時單調增加的行ID。如果InnoDB自動生成聚集索引,則索引包含行ID值。否則,該列不會出現在任何索引中。

回滾段中的undo日誌分爲插入undo日誌和更新undo日誌。插入undo日誌只在事務回滾時需要,並能夠在事務提交時儘快丟棄。而更新undo日誌在一致讀中也會使用,只有在不存在InnoDB爲其分配了快照的事務之後,才能丟棄這些快照。在一致讀取中,該快照可能需要更新撤消日誌中的信息來構建數據庫行的早期版本。

定期提交事務,包括那些只發出一致讀取的事務。否則,InnoDB無法從update undo日誌中丟棄數據,並且回滾段可能會變的過大,佔滿你的表空間。

回滾段中undo log記錄的物理大小,通常小於相應的插入行或更新行。你可以使用這個信息來計算回滾段所需的空間。

在InnoDB的多版本模式中,當你通過sql語句刪除一個記錄行時,它並不會馬上從數據庫中被物理刪除。InnoDB只有在丟棄 爲刪除寫入的update undo日誌記錄時,纔會物理刪除相關的行和索引記錄。這個刪除操作稱之爲purge(清理),並且這個操作執行很快,通常是與執行刪除的sql語句相同數量級的耗時。

如果以大約相同的速率小批量地插入和刪除表中的行,清理線程可能會開始落後,表也會由於所有”死“行記錄的堆積變的越來越大,使得任何事情都受磁盤限制並且非常緩慢。在這種情況下,可以通過調整innodb_max_purge_lag系統變量來限制新行操作,並分配更多資源給清理線程。

多版本和二級索引

InnoDB多版本控制(MVCC)在處理二級索引和聚簇索引時有所不同。聚簇索引中的記錄是就地更新,它們的隱藏系統字段指向undo log,從中可以重建記錄的早期版本。與聚簇索引記錄不同,二級索引記錄並不包含隱藏系統字段,並且它們也不會就地更新。

當一個二級索引列被更新時,舊的二級索引記錄會被標記刪除,新的記錄被插入,並且已經標記刪除的記錄最終會被清理。當一個二級索引記錄被標記刪除,或者二級索引頁被一個新的事務更新時,InnoDB會在聚簇索引中查找數據庫記錄。在聚簇索引中,記錄的DB_TRX_ID會被檢查,如果記錄在讀事務開始之後被修改,那麼記錄的正確版本會從undo log中找回。

如果二級索引記錄被標記刪除,或二級索引頁被更新的事務更改,那麼不會使用覆蓋索引技術。InnoDB會從聚簇索引中查找記錄,而不是從索引結構中返回值。

然而,如果開啓了索引條件下推(ICP)優化項,並且部分WHERE條件評估後可以只使用索引覆蓋的字段,MySQL服務器仍然將WHERE條件的這一部分向下推送到存儲引擎,在那裏使用索引對其進行評估。如果沒有找到匹配記錄,就會避免聚簇索引查找。如果找到了匹配記錄,哪怕是在標記爲刪除的記錄中,InnoDB也會在聚簇索引中查找記錄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章