ACSR(Auto Crash Safey Recovery)自動的故障安全恢復
更新操作
在一行數據被更新的時候

1、在使用BEGIN開啟事務時,會先給.ibd文件中分配一個TXID號和LSN號,假設為tx_01與lsn1001
2、在UPDATE執行時,MySQL會找到需更新數據的數據頁,并將其內容加載到data buffer pool中,由DBWR(double write)線程記錄變更數據頁的內容,并且記錄好TXID和更新LSN號,此時將產生臟頁與臟數據
3、使用LOGBWR(log double write)線程,將更新前的數據頁變化內容與TXID號以及LSN號記錄到undo log buffer中
4、使用LOGBWR(log double write)線程,將更新后的數據頁變化內容與TXID號以及LSN號記錄到redo log buffer中
現在,基于WAL原則為了應對用戶進行ROLLBACK操作,LOGBWR(log double write)線程會將undo log buffer中的內容全部寫入到undo_log即ibdata1(MySQL5.7版本undo_log仍然存在于共享表空間中)文件中COMMIT操作
現在我們基于上面BEGIN后發生的情況執行COMMIT操作,內部會做以下的3件事:
1、執行COMMIT操作,基于WAL原則,LOGBWR線程會先將redo log buffer中記錄的日志信息寫入redo_log文件中,在日志信息完全寫入redo_log即ib_logfile文件后,會對該日志打上COMMIT的標志
2、觸發CKPT,將內存數據頁更新到磁盤中,并且更新磁盤數據頁文件userInfo.ibd中原有的LSN號,讓其與redo_log文件中的LSN號保持一致
3、清空內存undo log buffer、data buffer pool、redo log buffer以及磁盤上undo_log中的數據可以看到整個事務提交的過程是先寫日志,再落盤寫數據。
其實redo log buffer將數據刷新到redo_log文件中的策略除開自己手動執行COMMIT外還有另一種情況。
在多任務時,其他線程COMMIT操作也可能會導致整個redo log buffer的刷新,刷新的redo_log文件中會對本線程提交的事務打上NOCOMMIT的標記。
其實這種現象取決于data buffer pool中存儲的數據量占據data buffer pool總量的多少來決定,一般來說如果占據到70%左右就會觸發該現象,我們可以對其進行手動設置,但一般來說保持默認值即可。
回滾
現在我們基于上面BEGIN后發生的情況執行ROLLBACK操作,內部會做以下的2件事:
1、執行ROLLBACK操作,LOGBWR線程會將undo log buffer中的數據重寫回到data buffer pool中,并且會把內存臟頁數據恢復到最開始的值,然后對LSN號進行回滾更正
2、清空內存undo log buffer、redo log buffer以及磁盤上undo_log中的數據前滾
MySQL : 在啟動時,必須保證redo日志文件和數據文件LSN必須一致, 如果不一致就會觸發CSR,最終保證一致
情況一:
我們做了一個事務,begin;update;commit.
1.在begin ,會立即分配一個TXID=tx_01.
2.update時,會將需要修改的數據頁(dp_01,LSN=1001),加載到data buffer中
3.DBWR線程,會進行dp_01數據頁修改更新,并更新LSN=1002
4.LOGBWR日志寫線程,會將dp_01數據頁的變化+LSN+TXID存儲到redobuffer
5. 執行commit時,LGWR日志寫線程會將redobuffer信息寫入redolog日志文件中,基于WAL原則,
在日志完全寫入磁盤后,commit命令才執行成功,(會將此日志打上commit標記)
6.假如此時宕機,內存臟頁沒有來得及寫入磁盤,內存數據全部丟失
7.MySQL再次重啟時,必須要redolog和磁盤數據頁的LSN是一致的.但是,
此時dp_01,TXID=tx_01
磁盤是LSN=101,dp_01,TXID=tx_01,redolog中LSN=102
MySQL此時無法正常啟動,MySQL觸發CSR.在內存追平LSN號,觸發ckpt,將內存數據頁
更新到磁盤,從而保證磁盤數據頁和redolog LSN一值.這時MySQL正常啟動
以上的工作過程,我們把它稱之為基于REDO的"前滾操作"
Log sequence number: 當前系統最大的LSN號
log flushed up to:當前已經寫入redo日志文件的LSN
pages flushed up to:已經將更改寫入臟頁的lsn號
Last checkpoint at就是系統最后一次刷新buffer pool臟中頁數據到磁盤的checkpoint
以上4個LSN是遞減的,即: LSN1>=LSN2>=LSN3>=LSN4.
比對redo的lsn和數據頁的lsn,如果數據頁的lsn比redo小,
那么就需要通過redo對數據頁進行重做。

前滾回滾
如果在COMMIT操作過程前發生了宕機,此時內存中的數據會全部丟失,但是恰好宕機前一秒由于其他線程的COMMIT操作導致了整個redo log buffer的自動刷新,此時redo_log文件中已經寫入了剛剛本線程操作事務的TXID號以及LSN號且標記此次操作是NOCOMMIT狀態的情況下重啟mysqld.service服務時將會產生如下情況
1、重啟mysqld.service服務,發現redo_log中記錄的LSN號和ibd文件中記錄的LSN號不一致,將觸發CSR自動故障恢復機制的第一個階段,前滾操作開始
2、通過redo_log文件中的變更記錄日志,在內存數據頁中恢復更改的數據
3、發現redo_log文件中的事務標記是NOCOMMIT,將觸發CSR自動故障恢復的第二個階段,回滾操作開始
4、通過undo log文件中的信息記錄,在內存數據頁中對前滾數據進行更改
5、使用LOGBWR線程,將更新的數據頁變化信息與TXID以及LSN號記錄到redo log buffer中
6、此時LOGBWR線程會先將redo log buffer中記錄的信息寫入到redo_log文件中,在日志信息完全寫入log file即ib_logfile文件后,會對該日志打上COMMIT標記
7、觸發CKPT,將內存數據頁更新到磁盤文件ibd中
8、回滾工作完成,redo_log中記錄的LSN號與ibd中記錄的LSN號一致,mysqld.service服務正常啟動最后修改時間:2021-12-01 07:35:54
「喜歡這篇文章,您的關注和贊賞是給作者最好的鼓勵」
關注作者
【版權聲明】本文為墨天輪用戶原創內容,轉載時必須標注文章的來源(墨天輪),文章鏈接,文章作者等基本信息,否則作者和墨天輪有權追究責任。如果您發現墨天輪中有涉嫌抄襲或者侵權的內容,歡迎發送郵件至:contact@modb.pro進行舉報,并提供相關證據,一經查實,墨天輪將立刻刪除相關內容。




