《《MySQL運維內參》節(jié)選》要點:
本文介紹了《MySQL運維內參》節(jié)選,希望對您有用。如果有疑問,可以聯系我們。
書接上文,本篇介紹日志管理的最后一部分.
在存儲已經搞定之后,那么還需要繼續(xù)研究一個要寫入的UNDO日志記錄的格式是什么樣子的.關于記錄格式,之前也介紹過InnoDB表中行記錄(Compact)的格式,也介紹了REDO日志的記錄格式,其實都是本著省空間、高效率的宗旨來設計的,那么對于UNDO記錄也是一樣,但是因為UNDO日志有多個類型,針對不同的類型,其格式也不盡相同,UNDO日志的類型有下面幾種.
除了上面說到的Table????ID信息、主鍵信息之外,還會包括一些公有的信息,比如回滾段指針、最近更新事務號,這樣方便MVCC在回溯記錄時可以找到以前的版本,關于MVCC的內容在這里就不詳細展開了.
再回到記錄格式.因為記錄格式都不盡相同,所以這里只拿TRX_UNDO_INSERT_REC來舉例說明,下圖即為其格式.
每一個位置的解釋如下.
從圖中可以看到,很多位置的存儲都是壓縮存儲的,所以上面第六點說到,列數據長度用的字節(jié)個數有可能是若干個,這決定于InnoDB所使用的壓縮編碼方式.
這里需要注意的一點是,與REDO日志記錄存儲不同,UNDO日志的存儲,是不會跨頁面的,所以在頁面頭中關于日志存儲的開始位置和結束位置就至關重要了.
其他類型的回滾記錄,這里就不再介紹了,大致結構是一樣的,只不過內容可能不盡相同.
需要注意的一點是,假如一個表中有多個索引,在修改一行數據時,回滾日志中也只會記錄聚簇索引中的信息,而其他二級索引是不會被記錄的.這是因為聚簇索引和二級索引中的每一行都是一一對應的,所以不同操作對聚簇索引操作時,也都會對二級索引有相應的操作,這樣就沒必要對二級索引寫回滾日志了.
(注:配圖為2017.5.6 ACMUG上?;顒臃治黾钨e,微博美女DBA)
前面已經介紹過,UNDO日志的正確性是通過REDO的恢復來保證的,在REDO日志恢復完成之后,UNDO操作就可以安全地進行了.數據庫啟動過程中,執(zhí)行了用于REDO恢復的函數recv_recovery_from_checkpoint_start之后,就可以處理UNDO的數據了,InnoDB通過函數trx_sys_init_at_db_start來將所有回滾段相關的128*1024個UNDO掃描出來(如果存在就找到,不存在就忽略),找到之后,每一個UNDO段的狀態(tài)都已經清楚了,然后將它們都緩存起來.
然后再通過函數trx_lists_init_at_db_start依次處理每一個UNDO段,根據UNDO段的狀態(tài),決定后面將采取什么措施,如果狀態(tài)為TRX_UNDO_PREPARED和TRX_UNDO_ACTIVE,則這個UNDO段是需要做回滾操作的,否則是不需要的.決定回滾需求之后,再將最多128*1024個UNDO段按照上面提到的TRX_UNDO_TRX_NO從大到小的順序排序.
最后就在之前介紹關于InnoDB存儲引擎啟動時的函數recv_recovery_from_checkpoint_finish中,來做回滾的相關工作.在這個函數的最后可以看到以下內容.
它根據參數innodb_force_recovery來決定要不要做回滾操作,如果設置為3或3以上,就不回滾了,這樣可能導致數據庫邏輯上的不一致.
最終,InnoDB通過trx_rollback_or_clean_recovered來做回滾操作,通過掃描上面排序之后的鏈表,發(fā)現其還是以從大到小的順序遍歷,這個順序很重要,因為UNDO是反向操作,所以應該是先處理新產生的事務,后處理老的事務,通過事務號來區(qū)分新老關系.
針對每一個UNDO段,InnoDB會將所有狀態(tài)為ACTIVE的事務的UNDO日志掃描出來,然后一條一條地做回滾操作,UNDO日志記錄格式已經明確,掃描所有的日志就變得非常簡單,并且針對不同的操作,對應的回滾方式也已經清楚,等待所有的回滾段處理完成之后,整個數據庫的回滾操作也就完成了.回滾過程如下圖所示.
文章來自微信公眾號:DBAce
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4148.html