InnoDB多版本學習

bitifi發表於2016-07-05

InnoDB是一個多版本儲存引擎(multi-versioned storage engine),它保留髮生改變的行舊版本資訊來支援事務的併發性和回滾(rollback)特性。這些舊版本資訊儲存在回滾段(rollback segment),InnoDB使用在回滾段中的資訊以執行在一個事務回滾中的undo操作,它還使用這些資訊來建立行的早期版本資料來提供一致性讀(consistent read)。

 

InnoDB內部,資料庫為每行增加了三個欄位:

DB_TRX_ID  長度6位元組事務ID

記錄最近一次發生insertupdate行資料操作的事務識別符號,而對應delete操作實際上也不是直接刪除,只是用一個bit位去標示刪除標記。

DB_ROLL_PTR  長度7位元組回滾指標

這個回滾指標指向回滾段(undo segment)中的回滾記錄。如果行被更新,在行被update之前,undo log記錄包含的資訊必須根據被update的內容重建。

DB_ROW_ID  長度6位元組行ID

該欄位包含新行的Row Id,這個欄位只在Insert操作時單調遞增,DB_ROW_ID是需要一個互訴鎖的才能產生。Innodb產生的clustered index包括Row ID.從另一方面來說,除了Clustered Index外,其它的索引不會包含Row Id

 

Undo log在回滾段中被分為insertupdate兩塊undo log

Insert undo log 僅僅在事務回滾時需要,並且當事務提交後能儘快丟棄。

update undo log則用於一致性讀,但是隻有當InnoDB分配的快照(為保證一致讀在update undo log建立的較早版本的行資料)不再被事務呼叫時才被丟棄。

 

建議定期提交你的事務,包括那些僅發生一致性讀的事務。否則InnoDB將無法丟棄update undo log,導致回滾段越來越大最終爆滿undo所在表空間。

 

插入或者更新的資料對應的undo log記錄在回滾段中的物理大小通常小於行本身。你可以透過這些資訊來計算相關行在回滾段中所需要的空間。

 

Innodb的多版本設計中當執行delete語句時資料行並不會被立即刪除,僅當update undo log記錄被棄用並註明刪除標識時,相應的行和索引才會被真正的刪除。該操作被稱為purgepurge操作非常快,通常可能delete語句發生之後隨之發生。

 

如果對一張表進行頻繁的小批次insertdeletepurge執行緒處理會產生延時,表會因為這些“死”行(沒有發生物理刪除)變得越來越大,而導致效能下降。這種情況,減少對新行的操作,並透過調整innodb_max_purge_lag引數為執行緒分配更多的資源。

InnoDB提供了兩個引數innodb_max_purge_laginnodb_max_purge_lag_delay 來調整

innodb_max_purge_lag 預設為0(不延遲)。當purge執行緒落後時,控制INSERT, UPDATE, DELETE操作的延遲。

Innodb
事務系統維護事務列表,此事務列表包含被updatedelete操作標識為刪除的索引記錄,事務列表的長度表示
purge_lag的值。當purge_lag(事務列表的長度)大於innodb_max_purge_lag時,每個 INSERT, UPDATE,DELETE操作會延遲。

即當trx_sys->rseg_history_len超過了設定的innodb_max_purge_lag,就會影響DML操作最大delay不超過innodb_max_purge_lag_delay設定的時間,以microseconds來計算。

 

purge_lag可以透過show engine innodb status看到,如下:

purge_lag的值為20.

 

謹慎調整innodb_max_purge_laginnodb_max_purge_lag_delay引數,依據現在的設計,可能你的例項的吞吐量會急劇的下降。

 

多版本和輔助索引

InnodbMVCC對待輔助索引和聚集索引不一樣。

聚集索引clusteredindexes記錄在其中可以就地更新(替換),它們有隱藏的系統列undo log entries(事務號+回滾指標),從早期版本的記錄可以被重建。

輔助索引secondary indexes 不像聚集索引,輔助索引沒有隱藏的系統列(事務號+回滾指標),也不能就地更新。

 

當更新一個輔助索引欄位時,新的輔助索引插入,老的輔助索引記錄被新增delete刪除標記並且最終被purge。當一個輔助索引被標記刪除或者輔助索引的頁被新的事務更新了,Innodb從聚集索引中查詢資料庫記錄。在聚集索引中,如果在一個讀操作已開啟,記錄被更新,則檢查該記錄的DB_TRX_ID並且從undo log中檢索正確版本的記錄。

 

如果輔助索引被標記刪除或者被更新了,此時,覆蓋索引(covering index)技術是不可用的。Innodb從聚集索引中查詢記錄,而不是從索引結構返回值。

 

如果index condition pushdown (ICP)是開啟的,並且查詢的where條件部分能直接從索引中查詢,MySQL server層仍然會將where條件這部分推到儲存引擎然後對索引條件進行評估,使用這個索引把滿足的行從表中讀取出。如果找到匹配的行,即使已經被表示刪除的記錄,InnoDB會從聚集索引查詢記錄。

 

參考:

http://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html


http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_max_purge_lag

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-2121517/,如需轉載,請註明出處,否則將追究法律責任。

相關文章