Mysql

如何關閉或刷新遠端伺服器上的 binlog 文件

  • September 10, 2016

我正在使用這些mysqlbinlog --stop-never --read-from-remote-server標誌將我的 binlog 文件複製到輔助伺服器。如果主數據庫伺服器受到威脅,我想在遠端伺服器上重放二進制日誌,但我遇到了“目前”二進制日誌的問題。

使用mysqlbinlog將其轉換為 SQL 時,我總是收到如下錯誤:

錯誤:Log_event::read_log_event() 中的錯誤:“讀取錯誤”,data_len:2682,事件 _type:2 錯誤:無法讀取偏移量 4426095 處的條目:日誌格式錯誤或讀取錯誤

我假設此問題與此 binlog 文件尚未在主數據庫伺服器上關閉或刷新的事實有關。flush logs在主數據庫伺服器上執行後,我的文件沒有這個問題。

所以,我的問題是這樣的:如果主數據庫伺服器遭到破壞並且我無法執行flush logs,那麼只能訪問複製到遠端伺服器的 binlog 文件。如何清理、關閉或刷新在數據庫中斷事件時打開的二進制日誌?

在主伺服器上刷新日誌幾乎可以解決您的問題。當主日誌文件旋轉時,mysqlbinlog關閉目前文件並打開下一個文件,這會隱式刷新所有緩衝數據。

您無法像mysqlbinlog實際伺服器那樣觸發按需刷新其日誌,但我找到了一種觸發它以將文件保持在始終刷新狀態的方法,這似乎是改善結果的可行方法.

當 Oracle 將--raw選項添加到 中時,該選項mysqlbinlog--read-from-remote-server並且--stop-never可用於擷取主伺服器二進制日誌的實時備份時,他們至少忽略了一些看似顯而易見的事情。

鑑於該功能的記錄目的……

--raw選項可用於備份伺服器的二進制日誌。使用該--stop-never選項,備份是“實時的”,因為mysqlbinlog保持與伺服器的連接。

https://dev.mysql.com/doc/refman/5.6/en/mysqlbinlog.html#option_mysqlbinlog_raw

…這似乎是一個明顯的疏忽,mysqlbinlog不會在每次寫入後刷新其輸出流。

也許這就是為什麼他們把“活”放在引號裡。:)

我的測試證實mysqlbinlog,在傳遞時,在其緩衝區中留下了可能已被刷新的懸空數據,但這似乎是一個相當簡單的問題來解決。

例如,mysql-5.6.27/client/mysqlbinlog.cc第 2477 行的這個小變化:

2477c2477
<         if (my_fwrite(result_file, net->read_pos + 1 , len - 1, MYF(MY_NABP)))
---
>         if (my_fwrite(result_file, net->read_pos + 1 , len - 1, MYF(MY_NABP)) || fflush(result_file))

此更改導致通過mysqlbinlog不斷匹配返回的大小來創建文件的大小SHOW MASTER STATUS;,而不是看起來總是落後幾個字節。我一直都知道這種輕微的滯後,但從未深入研究過。當然,不斷刷新緩衝區是有代價的,但這似乎是出於“備份”目的不可商量的必要性。請注意,這只是使用者空間緩衝區的刷新,它不是一個fsync()或類似的,所以我認為它在性能方面不會有那麼不同……而且無論如何,它不會影響主人。

使用邏輯||是因為my_fwrite()成功時返回 0,所以我們短路並且如果失敗則不嘗試刷新,如果任何一個操作失敗,我們都會出錯,因為fflush()成功時也返回 0。

此更改應顯著改善您看到的行為。

當然,您仍然有可能最終得到一個不完整的日誌,因為它仍然是一個打開的文件並且仍在被寫入……但是在低流量環境中測試此修復時,熱複製文件會導致對我來說可用的二進制日誌——否則,在相同的環境中,使用庫存二進製文件時文件結尾幾乎總是不完整的。

對於不同的版本(僅限 5.6+ - 此功能在 5.6 之前根本沒有實現),原始碼中的行可能會有所不同,但它應該仍然很容易發現,並且與此處指示的行號相距不遠。

Facebook 的 MySQL 5.6 分支具有類似但更複雜的修復程序,以及一個新選項--flush-result-file,它使刷新變得不那麼激進,但可配置。但是,我發現以目前的形式編譯是不必要的困難,所以我開發了上面的小更新檔。


只要您正在修補 mysqlbinlog,您可能會發現另一個對解決另一個設計疏忽有用的小調整。官方發行版中的mysqlbinlog實用程序缺乏對--compress命令行選項的支持(儘管 Percona 很明智地將其添加到他們的.)

但是,啟用壓縮也很容易。我剛剛為這個問題想出了上面的修復程序,但是我已經使用下面的修復程序已經有一段時間了,因為 - 再次 - 在我看來,它一直是一個明顯缺失的功能。

從 5.6.27 源碼來看,它看起來像這樣:

1948c1948
<   if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
---
>   if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, CLIENT_COMPRESS))

此更改不支持傳遞--compress命令行選項——它只是在與主伺服器的連接上打開客戶端壓縮協議,對於任何支持它的主伺服器(它們基本上都這樣做),從而減少網路數量傳輸日誌所需的頻寬 - 有時為 10:1 或更高,具體取決於特定的有效負載。它不會更改生成文件的內容——它只是啟用了對穿越網路的數據的壓縮。slave_compressed_protocol在網路上,從主伺服器的角度來看,這與在從伺服器上啟用具有相同的效果。(文件有歧義,但這個設置對主伺服器沒有影響,除非主伺服器也是另一台伺服器的從伺服器。)

引用自:https://dba.stackexchange.com/questions/149191