1.什麼是binlog?
2.binlog可以用來幹什麼?
3.怎麼樣使用binlog?
binlog是記錄所有資料庫表結構變更(例如CREATE、ALTER TABLE…)以及表資料修改(INSERT、
UPDATE、DELETE…)的二進位制日誌。實際落庫產生的日誌(事務提交後)。
我們先看一下Mysql資料更新的流程:
binlog可以幹什麼?
• 透過如上所述,我們知道binlog是mysql的已提交日誌,是實際落庫的,那麼如果可以監聽到binlog那麼我們可以用來處理DB主從同步,跨庫同步,資料備份,同步ES,快取重新整理等等
怎麼樣使用binlog?
準備工作
1.檢查binlog是否開啟
SHOW GLOBAL VARIABLES LIKE ‘log_bin%’; 結果返回不等於ON時代表關閉
可以透過my.ini配置檔案(linux中為my.cnf) log-bin=mysql-bin //指定binlog日誌檔案的名稱,可以根據實際需求進行命名。 binlog-format=ROW //設定binlog的格式,下面會解釋這三種格式。
2.檢查binlog格式
SHOW GLOBAL VARIABLES like ' binlog_format%’;
mysql binlog 分為三種模式(STATEMENT,ROW,MIXED)
- Statement(Statement-Based Replication,SBR):每一條會修改資料的 SQL 都會記錄在 binlog 中
- Row(Row-Based Replication,RBR):不記錄 SQL 語句上下文資訊,僅儲存哪條記錄被修改
- Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合體
這裡我們設定Row即可
SET GLOBAL binlog_format = 'ROW’;
SET GLOBAL binlog_row_metadata = ‘FULL’;//8.0版本以下不需要設定
現在準備工作完成,可以開始寫程式碼訂閱master節點去獲取binlog資訊了,再次之前我們先了解下 binlog的儲存原理
3.多檔案儲存
mysql 將資料庫更新操作對應的event記錄到本地的binlog檔案中,顯然在一個檔案中記錄所有的 event是不可能的,過大的檔案會給我們的運維帶來麻煩,如刪除一個大檔案,在I/O排程方面會給我們帶來不可忽視的資源開銷。
因此,目前基本上所有支援本地檔案儲存的元件,如MQ、Mysql等,都會控制一個檔案的大小。在資料量較多的情況下,就分配到多個檔案進行儲存。
在mysql中可以透過
show binlog events;
得到binlog的log_name(檔名)和大小以及pos(偏移量位置)
這兩個會在後面傳送dump到master節點去訂閱的時候用到,代表從binlog的哪處位置開始訂閱,master 就會在EventStream中傳送此檔案節點之後的所有資料庫變更資訊
4.Binlog管理事件
所謂binlog管理事件,官方稱之為binlog managent events,你可以認為是一些在任何模式下都有可能會出現的事件,不管你的配置binlog_format是Row、Statement還是Mixed。
每個binlog檔案總是以Format Description Event作為開始,以Rotate Event結束作為結束。如果你使用的是很古老的Mysql版本中,開始事件也有可能是START EVENT V3,而結束事件是Stop Event。在開始和結束之間,穿插著其他各種事件。
在Event_Type列中,我們看到了三個事件型別:
- Format_desc:也就是我們所說的Format Description Event,是binlog檔案的第一個事件。在Info列,我們可以看到,其標明瞭Mysql Server的版本是8.0,Binlog版本是4。
- Previous_gtids:該事件完整名稱為,PREVIOUS_GTIDS_LOG_EVENT。熟悉Mysql 基於GTID複製的
同學應該知道,這是表示之前的binlog檔案中,已經執行過的GTID。需要我們開啟GTID選項,這個事件才會有值,在後文中,將會詳細的進行介紹。
- Rotate:Rotate Event是每個binlog檔案的結束事件。在Info列中,我們看到了其指定了下一個 binlog檔案的名稱是mysql-bin.000004。
5.開始傳送一個dump到master節點
serverId代表此slave節點的id(不要跟master節點重複),訂閱binlog需要模擬一個slave(從節點)去向master節點傳送dump,後續就會接收的訂閱返回的事件流資訊 filename和position前面提到過的檔名和偏移量
傳送成功後就會接收到master節點返回的event資訊
每個binlog事件都以一個事件頭(event header)開始,然後是一個binlog事件型別特定的資料部分,稱為事件體(event body)。
事件體的具體結構與事件型別相關,以QUERY_EVENT型別為例,儲存格式如下:
常見的事件型別有:
- FORMAT_DESCRIPTION_EVENT:該部分位於整個檔案的頭部,每個binlog檔案都必定會有唯一一個該event
- PREVIOUS_GTIDS_EVENT:包含在每個binlog的開頭,用於描述所有以前binlog所包含的全部*GTID*的一個集合(包括已經刪除的binlog)
- GTID_EVENT/ANONYMOUS_GTID_EVENT:每一個Query事務前都會有這樣的一個GTID_EVENT,如果未開啟則是ANONYMOUS_GTID_EVENT。
事務開始時,執行的BEGIN操作;ROW格式中的DDL操作等
- TABLE_MAP_EVENT:每個DML事務之前,都會有一個TABLE_MAP_EVENT,記錄操作對應的表的資訊。
- WRITE_ROW_EVENT:插入操作。
- DELETE_ROW_EVENT:刪除操作。
- UPDATE_ROW_EVENT:更新操作。記載的是一條記錄的完整的變化情況,即從前量變為後量的過程 • XID_EVENT:主要是事務提交的時候回在最後生成一個xid號,有這個便代表事務已經成功提交了
- ROTATE_EVENT:Binlog結束時的事件,與一樣僅有一個
具體的原始碼可以透過以下連結去下載:
https://github.com/kogel-net/Kogel.Subscribe
尾言
這個輪子是在前兩年時候寫的,那時候想利用mysql的cdc解決快取重新整理的問題,但是找了一圈發現只有 java開源的輪子例如canal,flinkcdc等,c#社群好像並無此類似輪子就想寫一個,完善下c#/.net社群,希望以後.net發展能夠越來越好吧。