您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>java源碼下載>

MySQL InnoDB Update和Crash Recovery流程詳解

大?。?/span>0.5 MB 人氣: 2017-09-27 需要積分:2

  1.2.3 什么是Log Sequence Number (LSN)?

  一個(gè)64位無(wú)符號(hào)整數(shù),表示Redo Log系統(tǒng)中的時(shí)間點(diǎn),也是事務(wù)寫入Redo Log的字節(jié)總量,從日志初始化開始計(jì)數(shù)(數(shù)據(jù)庫(kù)初始化安裝時(shí)間點(diǎn)開始且單調(diào)遞增)

  LSN不僅存在于Redo Log中,在每個(gè)數(shù)據(jù)頁(yè)中都保存著一個(gè)LSN,在進(jìn)行數(shù)據(jù)恢復(fù)時(shí)通過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ù)文件等問題。

  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)行過程中都是使用這種方式刷臟,在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ù)開始點(diǎn)的一個(gè)64位無(wú)符號(hào)整數(shù)

  每個(gè)事務(wù)的事務(wù)號(hào)增量增加

  事務(wù)號(hào)會(huì)寫入聚簇索引的每個(gè)記錄中

  最大事務(wù)號(hào)會(huì)寫入系統(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ì)寫入U(xiǎn)ndo Log Header

  TRX_NO可用于purge Undo Log中的舊版本記錄

  2. Update流程2.1 事務(wù)start(事務(wù)首次開啟)

  為這個(gè)事務(wù)分配事務(wù)ID(TRX_ID),該事務(wù)ID可能被寫入系統(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的修改記錄寫入Redo Log中

  在buffer pool中修改數(shù)據(jù)頁(yè),回滾段指針指向Undo Log中該記錄之前的版本

  將該記錄對(duì)應(yīng)的數(shù)據(jù)頁(yè)變更部分寫入U(xiǎn)ndo Log中

  buffer pool中該記錄修改之后的數(shù)據(jù)頁(yè)被標(biāo)記為”臟頁(yè)”(需要刷新到磁盤的數(shù)據(jù)頁(yè))

  2.3 此時(shí)其他事務(wù)的修改會(huì)怎樣?

  一旦記錄被修改,即使沒有提交,其他事務(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的修改記錄寫入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)寫入到了Redo Log中且已經(jīng)落盤

  如果開啟了雙寫,則先將臟頁(yè)刷新到雙寫緩沖區(qū)(并等待同步)

  將每個(gè)臟頁(yè)從buffer pool中寫入最終目的地:表空間文件中的

  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)中并沒有地方單獨(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?。┑呐K頁(yè)已刷新到表空間文件,如果存在有比Checkpoint LSN大的臟頁(yè),則立即刷新臟頁(yè)到數(shù)據(jù)文件中。說(shuō)白了Checkpoint機(jī)制主要作用就是用于刷新臟頁(yè)。

  把Checkpoint LSN寫到Redo Log Header中 (從這個(gè)Checkpoint LSN開始,之前的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)閉的

  打開Redo Logs和系統(tǒng)表空間文件(ibdataN)

  讀取并從中找到最大的Checkpoint LSN

  從最近的Checkpoint 開始往后掃描Redo Log

  如果能夠找到Redo Log記錄,說(shuō)明還有數(shù)據(jù)頁(yè)的更改沒有刷新到數(shù)據(jù)文件上,啟動(dòng)Crash Recovery,使用Redo Log來(lái)恢復(fù)數(shù)據(jù)的一致性

  3.3 使用所有獨(dú)立表空間的表名和表空間ID創(chuàng)建一個(gè)名稱到ID的映射

  打開datadir下的所有.ibd文件

  在這些表空間文件的offset 0的頁(yè)(FSP_HDR頁(yè))頭讀取其表空間ID(FSP_HDR頁(yè)中FSP Header的前四個(gè)字節(jié)記錄著表空間ID)

  將表空間ID與表名建立映射

非常好我支持^.^

(1) 100%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?