redo,undo,binlog詳解


一.redo log 

1.定義:redo log是物理日志,記錄的是數據頁的物理修改

2.修改redo log的個數和大小:大小:innodb_log_file_size;個數:innodb_log_files_in_group (這兩個參數需重啟生效)

3.redo log 的組提交:redo組提交的思想是將多個事務redo log的刷盤合並,減少磁盤順序寫;Innodb的日志系統里面,每條redo log都有一個LSN(Log Sequence Number),LSN是單調遞增的。每個事務執行更新操作都會包含一條或多條redo log,各個事務將日志拷貝到log_sys_buffer時(log_sys_buffer 通過log_mutex保護),都會獲取當前最大的LSN,因此可以保證不同事務的LSN不會重復。那么假設三個事務Trx1,Trx2和Trx3的日志的最大LSN分別為LSN1,LSN2,LSN3(lsn1<lsn2<lsn3),它們同時進行提交,那么如果trx3日志先獲取到log_mutex進行落盤,它就可以順便把[lsn1-lsn3]這段日志也刷了,這樣trx1和trx2就不用再次請求磁盤io。

redo組提交的具體流程:

1)獲取 log_mutex
2)若flushed_to_disk_lsn>=lsn,表示日志已經被刷盤,跳轉5
3)若 current_flush_lsn>=lsn,表示日志正在刷盤中,跳轉5后進入等待狀態
4)將小於LSN的日志刷盤(flush and sync)
5)退出log_mutex
備注:lsn表示事務的lsn,flushed_to_disk_lsn和current_flush_lsn分別表示已刷盤的LSN和正在刷盤的LSN。
 
redo 刷盤的觸發條件:

刷日志到磁盤有以下幾種規則:

1.發出commit動作時。已經說明過,commit發出后是否刷日志由變量 innodb_flush_log_at_trx_commit 控制。

2.每秒刷一次。這個刷日志的頻率由變量 innodb_flush_log_at_timeout 值決定,默認是1秒。要注意,這個刷日志頻率和commit動作無關。

3.當log buffer中已經使用的內存超過一半時。

4.當有checkpoint時,checkpoint在一定程度上代表了刷到磁盤時日志所處的LSN位置。

 

二.undo log 

undo log有兩個作用:提供回滾和多個行版本控制(MVCC)。在數據修改的時候,不僅記錄了redo,還記錄了相對應的undo,如果因為某些原因導致事務失敗或回滾了,可以借助該undo進行回滾。

undo log和redo log記錄物理日志不一樣,它是邏輯日志。可以認為當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。

當執行rollback時,就可以從undo log中的邏輯記錄讀取到相應的內容並進行回滾。有時候應用到行版本控制的時候,也是通過undo log來實現的:當讀取的某一行被其他事務鎖定時,它可以從undo log中分析出該行記錄以前的數據是什么,從而提供該行版本信息,讓用戶實現非鎖定一致性讀取。

undo log是采用段(segment)的方式來記錄的,每個undo操作在記錄的時候占用一個undo log segment。innodb存儲引擎對undo的管理采用段的方式。rollback segment稱為回滾段,每個回滾段中有1024個undo log segment。在以前老版本,只支持1個rollback segment,這樣就只能記錄1024個undo log segment。后來MySQL5.5可以支持128個rollback segment,即支持128*1024個undo操作,還可以通過變量innodb_undo_logs參數定義,默認是128個

另外,undo log也會產生redo log,因為undo log也要實現持久性保護。

 

三.二階段提交

 

二階段提交描述:在對應的Redo日志記錄上打上prepare標記。隨后會寫入Binlog並執行fsync(系統調用,對Binlog執行磁盤同步),最后在Redo日志記錄上打上commit標記表示記錄已提交完成。

所以是binlog先落盤,redo后落盤

實例恢復:

•對於活躍狀態的事務,可直接進行回滾。

•對於Prepare狀態的事務,如果該事務對應的Binlog已經記錄則提交,否則回滾事務。Prepare狀態就是圖19-4中在Redo日志中所打上的prepare標記的狀態。

先落盤binlog的原因:

由於MySQL是插件式數據庫,可能會同時使用多個存儲引擎,像InnoDB這種存儲引擎有Redo日志可以做實例恢復,但是其他的存儲引擎可能沒有Redo日志而就是依賴Binlog做實例恢復。那么如果先寫Redo日志並打上commit標記,這時若發生宕機,使用InnoDB存儲引擎就可以做實例恢復,將數據恢復過來,而其他的存儲引擎由於Binlog沒有寫成功可能就無法恢復數據了,那么可能就會出現數據不一致的情況。所以,在MySQL中做實例恢復時會依賴Binlog,以Binlog中的內容為准。

 

四.sync_binlog參數

sync_binlog參數控制着二進制日志寫入磁盤的過程,它的有效值為0、1、N,每個值得含義分別代表如下:

0:默認值,事務提交后,將二進制日志從緩沖寫入磁盤,但是不進行刷新操作(fsync()),此時只是寫入了操作系統緩沖,若操作系統宕機則會丟失部分二進制文件。

1:事務提交后,將二進制文件寫入磁盤並立即執行刷新操作(fsync()),相當於是同步寫入磁盤,不經過操作系統的緩存。

N:每寫N次操作系統緩沖就執行一次刷新操作。

 

五.binlog的組提交

FLUSH 階段

1) 持有Lock_log mutex [leader持有,follower等待]

2) 獲取隊列中的一組binlog(隊列中的所有事務)
3) 將binlog buffer到I/O cache
4) 通知dump線程dump binlog
SYNC階段
這個階段和參數sync_binlog有關系,
1) 釋放Lock_log mutex,持有Lock_sync mutex[leader持有,follower等待]
2) 將一組binlog 落盤(sync動作,最耗時,假設sync_binlog為1)。
COMMIT階段(這里不用寫redo log,在prepare階段已寫)
1) 釋放Lock_sync mutex,持有Lock_commit mutex[leader持有,follower等待]
2) 遍歷隊列中的事務,逐一進行innodb commit
3) 釋放Lock_commit mutex
4) 喚醒隊列中等待的線程
總結起來就是 :
FLUSH 階段-----將binlog從binlog buffer到I/O cache刷新;
SYNC階段-------將binlog從I/O cache到底層磁盤;
COMMIT階段----innodb commit ,清除undo信息;

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM