如何關閉或刷新遠端伺服器上的 binlog 文件
我正在使用這些
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
在網路上,從主伺服器的角度來看,這與在從伺服器上啟用具有相同的效果。(文件有歧義,但這個設置對主伺服器沒有影響,除非主伺服器也是另一台伺服器的從伺服器。)