db-cdc之mysql 深入瞭解並使用binlog

Kogel發表於2023-10-19

1.什麼是binlog?

2.binlog可以用來幹什麼?

3.怎麼樣使用binlog?

 

binlog是記錄所有資料庫表結構變更(例如CREATE、ALTER TABLE…)以及表資料修改(INSERT、

UPDATE、DELETE…)的二進位制日誌。實際落庫產生的日誌(事務提交後)。

我們先看一下Mysql資料更新的流程:

db-cdc之mysql 深入瞭解並使用binlog

 

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(偏移量位置)

db-cdc之mysql 深入瞭解並使用binlog

這兩個會在後面傳送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節點

db-cdc之mysql 深入瞭解並使用binlog

serverId代表此slave節點的id(不要跟master節點重複),訂閱binlog需要模擬一個slave(從節點)去向master節點傳送dump,後續就會接收的訂閱返回的事件流資訊 filenameposition前面提到過的檔名偏移量

傳送成功後就會接收到master節點返回的event資訊

每個binlog事件都以一個事件頭(event header)開始,然後是一個binlog事件型別特定的資料部分,稱為事件體(event body)。

事件體的具體結構與事件型別相關,以QUERY_EVENT型別為例,儲存格式如下:

db-cdc之mysql 深入瞭解並使用binlog

常見的事件型別有:

  • 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發展能夠越來越好吧。

相關文章