MySQL-正確的解析行事件

行事件一共有3類:TALBE_MAP_EVENT、ROWS_EVENT、ROWS_QUERY_EVENT.其中的ROWS_EVENT分爲WRITE_ROWS_EVENT、UPDATE_ROWS_EVENT、DELETE_ROWS_EVENT。這三種每個又分爲3個版本:v0 v1 v2。行事件表明了一個數據庫行是如何變化的,那麼如何通過序列化的二進制數據解析出來變化的信息呢?

每次發起同步的時候,MySQL總會發送一個ROTATE事件,這不是一個真正的ROTATE事件,他僅僅用於指出當前主庫的binlog事件偏移量是多少。區分真假ROTATE事件的方式是出現本應設置非0的字段,其值是0,比如timestamp。

ROTATE後面跟隨Format_description事件。這個有兩個字段非常重要,標明同步的版本、所有事件(UNKNOWN_EVENT除外)的頭部長度。

當一次行數據發生變更的時候(insert、update、delete),首先會發送一個QUERY事件,也可能是ROWS_QUERY事件。區別在於後者是MySQL5.6才引入的,會記錄QUERY內容,而前者就記錄了一個“BEGIN”(好奇怪的說)。具體是不是發送ROWS_QUERY,首先要確定這是一個ROW事件,其次依賴於MySQL的設定。在MySQL啓動時候設置--binlog-rows-query-log-events或者會話設置了binlog_rows_query_log_events,纔會出現這種事件。由於設置了這個選項會導致使用5.5或者以前的從庫無法同步,所以一般爲OFF。

下一個事件就是TABLE_MAP。每個ROWS_EVENT並不會記錄表的基本信息,所以需要將數據和表映射起來。TABLE_MAP主要就是記錄這種映射關係,他會指出數據庫名、表名、表ID,這樣就能從ROWS_EVENT裏面的表ID對應到具體的數據庫名。另一個比較重要的字段是列使用位圖。由若干個字節表示,指出哪些列被使用。每列對應一位,0是沒使用,1是使用。這是另一個不理解的設置,至少我看到的都是全1的。還有個字段是Type和Metadata,記錄每列的類型、每類數據的基本信息(每類數據定義的元數據代表的意義都不同,比如有的代表長度等等)。

後面會跟隨一個或若干個ROWS_EVENT。每個EVENT都會有一個null-bit-map,表示每個字段是不是爲NULL,因爲如果是NULL的話是不記錄在最後的行數據字段中的。也是每個字段用一位來表示。數據字段記錄具體的行數據。如果是WRITE,則記錄添加的行;如果是DELETE,則記錄刪除的行的標識;如果是UPDATE,先記錄刪除的行的標識,再記錄新的行數據。默認情況下,行標識就是整個行數據,實際上,部分數據有的時候就能夠標識出一個行了,比如有主鍵的行就記錄主鍵就可以標識。如果開啓了--binlog-row-image選項爲enumeration,或者會話中設置了binlog_row_image

爲enumeration,纔不會記錄全行。這個選項在5.5和之前的版本中都是不支持的。

最後就是一個XID事件了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章