Binlog是mysql以二進制形式打印的日志,它默認不加密,不壓縮。每個正常的binlog文件頭部,有4個字節的標記,值為0xfe 0x62 0x69 0x6e。LOG_EVENT是binlog裡的單位,即正常情況下binlog按照逐LOG_EVENT的形式增長。除去頭部的標記,binlog就是一個LOG_EVENT的序列。每個LOG_EVENT都獨立單元,沒有互相引用的關系,它也有自己的二進制頭部,主要是記錄了時間戳、類型標記等描述信息。
Mysql把磁盤操作的實現封裝在IO_CACHE結構裡,這也方便了我們對binlog的研究和描述,後文如果沒有特別說明,讀寫binlog與讀寫IO_CACHE的含義相同。為了解mysql寫入binlog的過程,可以找一個sql語句的處理過程進行跟蹤。以update為例,在最簡單的情況下,mysql會先調用為存儲引擎開放的接口ha_update_row,然而執行binlog_query對binlog進行寫操作。
這樣處理的原因是,在主從備份的場景下,如果主庫先寫入binlog成功、在執行update的過程中crash,從庫有可能執行update成功,此時主庫重啟之後,與從庫的數據不一致。如果update操作發生在事務性的表上,在寫入binlog之後會執行開放接口ha_autocommit_or_rollback,由存儲引擎判斷操作結果。
在主從備份的場景下,主庫相當於server,從庫相當於client,雙方采用tcp短連接。從庫發出讀取日志的請求,主庫接收請求、讀取本地binlog、然後發送給從庫。從庫接收日志,進行簡單校驗後寫本地日志,稱為relay log。此處從庫的流程專門由一個線程負責,稱為同步io線程。從庫還有一個線程,稱為同步sql線程。它的行為是,定期讀取relay log,解析並執行同步過來的sql語句。
下面回答幾個問題:
1.binlog的格式?
二進制順序存儲,不加密,不壓縮。
2.binlog使用WAL嗎?
No。
3.主庫發送binlog,是使用內存裡的copy嗎?
無法確定,很有可能是先從磁盤上讀一份,然後發送。
4.relaylog使用WAL嗎?
Yes。從庫接收到日志後,會先寫relay log。
5.binlog和relaylog的SQL是否一致?
在網絡傳輸正確性可靠的前提下,yes。