MySQL InnoDB Update和Crash Recovery流程詳解
推薦 + 挑錯(cuò) + 收藏(0) + 用戶評(píng)論(0)
1.2.3 什么是Log Sequence Number (LSN)?
一個(gè)64位無(wú)符號(hào)整數(shù),表示Redo Log系統(tǒng)中的時(shí)間點(diǎn),也是事務(wù)寫(xiě)入Redo Log的字節(jié)總量,從日志初始化開(kāi)始計(jì)數(shù)(數(shù)據(jù)庫(kù)初始化安裝時(shí)間點(diǎn)開(kāi)始且單調(diào)遞增)
LSN不僅存在于Redo Log中,在每個(gè)數(shù)據(jù)頁(yè)中都保存著一個(gè)LSN,在進(jìn)行數(shù)據(jù)恢復(fù)時(shí)通過(guò)LSN做比較運(yùn)算可以判斷出每個(gè)數(shù)據(jù)頁(yè)是否需要進(jìn)行恢復(fù)操作
1.2.4 什么是Checkpoint?
一個(gè)時(shí)間點(diǎn),由一個(gè)LSN值(Checkpoint LSN)表示的整型值,在Checkpoint LSN之前的每個(gè)數(shù)據(jù)頁(yè)(buffer pool中的臟頁(yè))的更改都已經(jīng)落盤(刷新到數(shù)據(jù)文件中),Checkpoint 完成后,在Checkpoint LSN之前的Redo Log就不再需要了。
Checkpoint技術(shù)是為了解決:全量Redo Log恢復(fù)時(shí)間太長(zhǎng)、buffer pool中的空閑頁(yè)不夠用時(shí)將臟頁(yè)刷新到磁盤數(shù)據(jù)文件、Redo Log空間不夠用時(shí)將臟頁(yè)刷新到磁盤數(shù)據(jù)文件等問(wèn)題。
Checkpoint方式有兩種:Sharp Checkpoint和Fuzzy Checkpoint(又可根據(jù)不同的場(chǎng)景細(xì)分)
Sharp Checkpoint:將所有的臟頁(yè)刷回磁盤,數(shù)據(jù)庫(kù)實(shí)例關(guān)閉時(shí)系統(tǒng)參數(shù)innodb_fast_shutdown設(shè)置為0,才需要把所有的臟頁(yè)都刷回磁盤,刷臟時(shí)系統(tǒng)hang住
Fuzzy Checkpoint:持續(xù)的每次只刷新一部分臟頁(yè)到磁盤,數(shù)據(jù)庫(kù)正常運(yùn)行過(guò)程中都是使用這種方式刷臟,在InnoDB內(nèi)部還可細(xì)分為如下幾種:
Master線程每秒/每十秒固定執(zhí)行Checkpoint
LRU list中空閑頁(yè)不夠時(shí),觸發(fā)Checkpoint從LRU list刷新臟頁(yè)以釋放足夠的空閑頁(yè)
Redo Log空間不夠時(shí),觸發(fā)Checkpoint從Flush list刷新臟頁(yè),Checkpoint執(zhí)行完成之后,在這個(gè)位置之前的Redo Log不再需要(即,可以循環(huán)覆蓋使用)
臟頁(yè)太多達(dá)到臟頁(yè)比例閥值(系統(tǒng)參數(shù)innodb_max_dirty_pages_pct和innodb_max_dirty_pages_pct_lwm控制臟頁(yè)比例閥值),觸發(fā)Checkpoint
1.2.5 什么是Rollback Pointer (ROLL_PTR)?
一個(gè)由rollback segment number、page number和page offset組成的指針,指向Undo Log中包含之前版本數(shù)據(jù)的具體Undo Log日志記錄。
可用于為任何數(shù)據(jù)記錄回退到一個(gè)歷史版本記錄、可用于mvcc中重建舊版本記錄、可用于事務(wù)回滾。
1.2.6 什么是Transaction ID (TRX_ID)?
表示事務(wù)開(kāi)始點(diǎn)的一個(gè)64位無(wú)符號(hào)整數(shù)
每個(gè)事務(wù)的事務(wù)號(hào)增量增加
事務(wù)號(hào)會(huì)寫(xiě)入聚簇索引的每個(gè)記錄中
最大事務(wù)號(hào)會(huì)寫(xiě)入系統(tǒng)表空間的TRX_SYS頁(yè)
1.2.7 什么是Transaction Serialization Number(TRX_NO) ?
一個(gè)64位無(wú)符號(hào)整數(shù),表示事務(wù)提交時(shí)的最大TRX_ID
TRX_NO在事務(wù)提交時(shí)會(huì)寫(xiě)入U(xiǎn)ndo Log Header
TRX_NO可用于purge Undo Log中的舊版本記錄
2. Update流程2.1 事務(wù)start(事務(wù)首次開(kāi)啟)
為這個(gè)事務(wù)分配事務(wù)ID(TRX_ID),該事務(wù)ID可能被寫(xiě)入系統(tǒng)表空間的TRX_SYS頁(yè)面中的最大的事務(wù)ID字段(Transaction ID)
* 如果系統(tǒng)表空間的TRX_SYS頁(yè)面中的最大的事務(wù)ID字段被更新,則該更新會(huì)被記錄到Redo Log中。
根據(jù)分配的TRX_ID創(chuàng)建read view。
2.2 記錄修改(每次只修改一行記錄)
分配Undo Log日志空間
拷貝該記錄修改之前的值到Undo Log中
將Undo Log的修改記錄寫(xiě)入Redo Log中
在buffer pool中修改數(shù)據(jù)頁(yè),回滾段指針指向Undo Log中該記錄之前的版本
將該記錄對(duì)應(yīng)的數(shù)據(jù)頁(yè)變更部分寫(xiě)入U(xiǎn)ndo Log中
buffer pool中該記錄修改之后的數(shù)據(jù)頁(yè)被標(biāo)記為”臟頁(yè)”(需要刷新到磁盤的數(shù)據(jù)頁(yè))
2.3 此時(shí)其他事務(wù)的修改會(huì)怎樣?
一旦記錄被修改,即使沒(méi)有提交,其他事務(wù)也可能會(huì)看到被修改后的記錄,這依賴于他們的事務(wù)隔離級(jí)別而定:
如果是RU隔離級(jí)別,則使用索引頁(yè)讀取最新版本記錄
如果是RU隔離級(jí)別,則查找記錄的最新提交版本
如果是RR隔離級(jí)別,則查找與其read view相對(duì)應(yīng)的記錄版本
任何需要使用索引頁(yè)來(lái)讀取比最新的版本記錄舊的版本記錄時(shí),都必須使用Undo Log來(lái)重建之前的版本記錄。
2.4 事務(wù)提交(顯式和隱式提交)
事務(wù)對(duì)應(yīng)的Undo Log頁(yè)被設(shè)置為”purge”(意味著當(dāng)這個(gè)Undo Log頁(yè)不再被任何其他事務(wù)引用時(shí)可以將其清除)
將Undo Log的修改記錄寫(xiě)入Redo Log中
Redo Log Buffer刷新到磁盤(是否刷盤取決于系統(tǒng)變量innodb_flush_log_at_trx_commit的設(shè)置)
2.5 后臺(tái)線程刷臟(后臺(tái)線程連續(xù)不斷地根據(jù)不同觸發(fā)機(jī)制觸發(fā)刷新)
查找最舊的“臟”頁(yè)面(修改時(shí)間最早的頁(yè)面)并將其添加到flush batch中
確保在flush batch中中最新的LSN號(hào)已經(jīng)寫(xiě)入到了Redo Log中且已經(jīng)落盤
如果開(kāi)啟了雙寫(xiě),則先將臟頁(yè)刷新到雙寫(xiě)緩沖區(qū)(并等待同步)
將每個(gè)臟頁(yè)從buffer pool中寫(xiě)入最終目的地:表空間文件中的
PS:對(duì)于后臺(tái)線程刷臟部分,執(zhí)行刷新臟頁(yè)時(shí),與該臟頁(yè)的事務(wù)是否提交無(wú)關(guān),只需要確保該頁(yè)對(duì)應(yīng)LSN號(hào)的Redo Log記錄落盤,而不會(huì)去判斷事務(wù)的狀態(tài)是否是提交還是未提交狀態(tài),因?yàn)?,?shù)據(jù)頁(yè)結(jié)構(gòu)中并沒(méi)有地方單獨(dú)記錄事務(wù)的狀態(tài)(即,無(wú)法判斷事務(wù)是否提交),只是在每行數(shù)據(jù)中有記錄事務(wù)號(hào)、回滾段指針(所以一個(gè)頁(yè)中也可能包含多個(gè)事務(wù)的修改記錄)。當(dāng)需要對(duì)某個(gè)事務(wù)進(jìn)行回滾時(shí),重新從表空間中讀取這個(gè)未提交的臟頁(yè),使用undo log中的反向數(shù)據(jù)進(jìn)行反向修改,然后再重新刷臟。
2.6 定期執(zhí)行Checkpoint
確保比Checkpoint 點(diǎn)更舊(比Checkpoint LSN小)的臟頁(yè)已刷新到表空間文件,如果存在有比Checkpoint LSN大的臟頁(yè),則立即刷新臟頁(yè)到數(shù)據(jù)文件中。說(shuō)白了Checkpoint機(jī)制主要作用就是用于刷新臟頁(yè)。
把Checkpoint LSN寫(xiě)到Redo Log Header中 (從這個(gè)Checkpoint LSN開(kāi)始,之前的Redo Log記錄不再需要)。
2.7 后臺(tái)線程Purge(后臺(tái)線程連續(xù)不斷地根據(jù)需要定期執(zhí)行Purge,包括Undo Log和歷史鏈表)
查找每個(gè)回滾段中不再需要的最舊的Undo Log
實(shí)際上是從索引中刪除任何帶有刪除標(biāo)記的記錄
釋放Undo Log頁(yè)
修剪history lists
3. Creash Recovery流程3.1 什么時(shí)候會(huì)進(jìn)行Crash Recovery?
實(shí)例崩潰之后重啟
使用一個(gè)備份還原(如:LVM 快照、xtrabackup備份)后
在“快速”(innodb_fast_shutdown不為0值關(guān)閉實(shí)例)關(guān)閉實(shí)例后重新啟動(dòng)
3.2 檢測(cè)實(shí)例是不是干凈地關(guān)閉的
打開(kāi)Redo Logs和系統(tǒng)表空間文件(ibdataN)
讀取并從中找到最大的Checkpoint LSN
從最近的Checkpoint 開(kāi)始往后掃描Redo Log
如果能夠找到Redo Log記錄,說(shuō)明還有數(shù)據(jù)頁(yè)的更改沒(méi)有刷新到數(shù)據(jù)文件上,啟動(dòng)Crash Recovery,使用Redo Log來(lái)恢復(fù)數(shù)據(jù)的一致性
3.3 使用所有獨(dú)立表空間的表名和表空間ID創(chuàng)建一個(gè)名稱到ID的映射
打開(kāi)datadir下的所有.ibd文件
在這些表空間文件的offset 0的頁(yè)(FSP_HDR頁(yè))頭讀取其表空間ID(FSP_HDR頁(yè)中FSP Header的前四個(gè)字節(jié)記錄著表空間ID)
將表空間ID與表名建立映射
非常好我支持^.^
(1) 100%
不好我反對(duì)
(0) 0%
下載地址
MySQL InnoDB Update和Crash Recovery流程詳解下載
相關(guān)電子資料下載
- 常用于緩存處理的機(jī)制總結(jié) 如何避免緩存雪崩問(wèn)題? 24
- 一文詳解ZGC關(guān)鍵技術(shù) 26
- SpringBoot物理線程、虛擬線程、Webflux性能比較 37
- Rust語(yǔ)言為什么這么卷? 21
- 什么是分布式鎖 Redis的五種分布式鎖方案 32
- Guava中這些Map的操作,讓我的代碼量減少了50% 70
- mysql經(jīng)典面試題及答案 63
- java實(shí)現(xiàn)定時(shí)器的四種方式 83
- 聊聊即將到來(lái)的MySQL5.7停服事件 179
- 基于Prometheus開(kāi)源的完整監(jiān)控解決方案 25