天天看點

mysql如何保證redolog和binlog的一緻性,安全性,效率。

<a href="http://dwchaoyue.blog.51cto.com/2826417/1784509" target="_blank">http://dwchaoyue.blog.51cto.com/2826417/1784509</a>

mysql如何保證redolog和binlog的一緻性,安全性,效率。

和資料安轉相關的參數

sync_binlog:控制binlog的重新整理方式(寫入到磁盤)

innodb_flush_log_at_trx_commit:在innodb下控制着redo的寫入方式

innodb_support_xa:外部事務,用來保證binlog和redo一緻性的,俗稱兩段式送出

binlog_order_commits:按照binlog的寫入順序送出事務,保證redo和binlog的已執行

binlog_max_flush_queue_time: leader線程搜集binlog的逾時時間

2pc送出(官方支援)

(redo日志在prepare階段就已經sync),絕大部分都比較支援這種說法

<a href="http://dev.mysql.com/doc/refman/5.6/en/binary-log.html" target="_blank">http://dev.mysql.com/doc/refman/5.6/en/binary-log.html</a>

<a href="http://blog.itpub.net/15480802/viewspace-1411356" target="_blank">http://blog.itpub.net/15480802/viewspace-1411356</a>

<a href="http://www.linuxidc.com/Linux/2015-11/124942.htm" target="_blank">http://www.linuxidc.com/Linux/2015-11/124942.htm</a>

<a href="http://www.2cto.com/database/201306/221413.html" target="_blank">http://www.2cto.com/database/201306/221413.html</a>

2pc流程:(sync_binlog = 1,innodb_flush_log_at_trx_commit = 1 )

1.prepare階段:sync redo 日志(未sync的redo存放于innodb_log_buffer_size中),系統自動完成

擷取prepare_commit_mutex(一個全局鎖,一次隻能被一個事務擷取)

2.生成binlog,将binlog寫入檔案系統(未送出之前binlog存放在binlog_cache_size中),sync binlog,這一步受sync_binlog控制

3.送出commit 将commit标志sync ,釋放prepare_commit_mutex(這一步應該受innodb_flush_log_at_trx_commit的控制)

違背了這個參數的定義:innodb_flush_log_at_trx_commit

觀點二:redo日志在最後的commit的時候才sync

<a href="http://blog.itpub.net/28218939/viewspace-1975809" target="_blank">http://blog.itpub.net/28218939/viewspace-1975809</a>

2pc流程:(官方沒有明顯的支援這種說法)

1.prepare階段:擷取prepare_commit_mutex

2.生成binlog,将binlog寫入檔案系統(未送出之前binlog存放在binlog_cache_size中),sync binlog

3.送出commit 将redo log sync ,釋放prepare_commit_mutex

這種方式會造成binlog的日志記錄多餘redo日志記錄,在恢複的時候是如何恢複? 難道是以binlog為準,

不管這個事務的redo有沒有送出 ,隻要寫binlog就認為該事務以送出(現階段還沒有找到有關該說法).

innodb資料恢複流程

1.查找未送出的redo日志(找xid)

2.用xid去binlog查找對應的日志記錄

3.如果有就認為這個事務是送出的,并補充commit。如果沒有就認為是沒有送出的,在恢複的時候就rollback事務

###################################################################################################

以上2pc日志寫入方式是在 mysql5.6之前的方式,當sync_binlog=1的時候 系統的性能非常糟糕。

從5.6 之後就開始采用BLGC方式寫2pc日志,來提升性能

BLGC具體流程如下:(每一個階段隻有一個活躍的線程)

flush stage:已完成perpare階段的線程隊列

sync stage:flush隊列逾時(binlog_max_flush_queue_time)或者沒有線程産生binlog了 ,flush隊列開始sync隊列,将binlog寫入磁盤(合并io)  

commit stage:隊列進入送出階段(這裡隻做送出操作,redo日志的寫入已經在prepare寫入)

個人了解:

flush stage:隊列中的第一個線程為leader線程,後面的線程為follower線程,leader線程主要負責收集待送出binlog的線程(線程準備階段之後自動進入flush階段),直到隊列為空,或者逾時(binlog_max_flush_queue_time),才進入sync stage

sync stage:如果flush stage隊列為空,則之前leader線程依然為leader線程,負責binlog的sync,否則變成follower線程(合并執行sync)

commit stage:sync完binlog的線程被放入commit隊列的末尾,等待送出

5.7 的組送出:

Step1. InnoDB Prepare,記錄目前的LSN到thd中。 

Step2. 進入 Group Commit 的flush stage;Leader搜集隊列,同時算出隊列中最大的LSN。 

Step3. 将InnoDB的redo log write/fsync到指定的LSN  

Step4. 寫Binlog并進行随後的工作(sync Binlog, InnoDB commit 

也就是将 redo log的write/sync延遲到了 binlog group commit的 flush stage 之後,sync binlog之前。

通過延遲寫redo log的方式,顯式的為redo log做了一次組寫入(redo log group write),并減少了(redo log) log_sys-&gt;mutex的競争。

組送出

<a href="http://www.tuicool.com/articles/rEZr2q" target="_blank">http://www.tuicool.com/articles/rEZr2q</a>

<a href="http://mysqllover.com/?p=581" target="_blank">http://mysqllover.com/?p=581</a>

innodb資料丢失的問題:

<a href="http://www.360doc.com/content/14/1019/00/12904276_418041635.shtml" target="_blank">http://www.360doc.com/content/14/1019/00/12904276_418041635.shtml</a>

組送出的了解:

<a href="http://www.bitscn.com/pdb/mysql/201407/226226.html" target="_blank">http://www.bitscn.com/pdb/mysql/201407/226226.html</a>

<a href="http://www.cnblogs.com/cchust/p/4439107.html" target="_blank">http://www.cnblogs.com/cchust/p/4439107.html</a>

本文轉自 lirulei90 51CTO部落格,原文連結:http://blog.51cto.com/lee90/1969656,如需轉載請自行聯系原作者

繼續閱讀