1. 程式人生 > >MySQLbinlog日誌03binlog日誌字節碼解析

MySQLbinlog日誌03binlog日誌字節碼解析

mys mon exec des 時間戳 eat 字節數 logs 適用於

本系列博客主要介紹MySQL數據庫的binlog日誌的相關內容,這個系列的主題包括:

MySQLbinlog日誌01binlog日誌基本操作

MySQLbinlog日誌02binlog日誌用於數據恢復

MySQLbinlog日誌03binlog日誌字節碼解析

MySQLbinlog日誌04binlog日誌字節碼解析之二Write_Rows事件

本博客主要內容包括:

binlog事件類型

binlog事件頭部結構

binlog字節碼分析的準備工作

binlog日誌文件MAGIC代碼

Format desc事件

Table map事件

下一篇博客

MySQLbinlog日誌04binlog日誌字節碼解析之二Write_Rows事件

將介紹:

Write rows事件

1. binlog事件類型

MySQL Server 5.7.22支持的事件類型如下所示,總共定義了38種。

START_EVENT_V3= 1,

QUERY_EVENT= 2,

STOP_EVENT= 3,

ROTATE_EVENT= 4,

INTVAR_EVENT= 5,

LOAD_EVENT= 6,

SLAVE_EVENT= 7,

CREATE_FILE_EVENT= 8,

APPEND_BLOCK_EVENT= 9,

EXEC_LOAD_EVENT= 10,

DELETE_FILE_EVENT= 11,

NEW_LOAD_EVENT= 12,

RAND_EVENT= 13,

USER_VAR_EVENT= 14,

FORMAT_DESCRIPTION_EVENT= 15,

XID_EVENT= 16,

BEGIN_LOAD_QUERY_EVENT= 17,

EXECUTE_LOAD_QUERY_EVENT= 18,

TABLE_MAP_EVENT = 19,

PRE_GA_WRITE_ROWS_EVENT = 20,

PRE_GA_UPDATE_ROWS_EVENT = 21,

PRE_GA_DELETE_ROWS_EVENT = 22,

WRITE_ROWS_EVENT_V1 = 23,

UPDATE_ROWS_EVENT_V1 = 24,

DELETE_ROWS_EVENT_V1 = 25,

INCIDENT_EVENT= 26,

HEARTBEAT_LOG_EVENT= 27,

IGNORABLE_LOG_EVENT= 28,

ROWS_QUERY_LOG_EVENT= 29,

WRITE_ROWS_EVENT = 30,

UPDATE_ROWS_EVENT = 31,

DELETE_ROWS_EVENT = 32,

GTID_LOG_EVENT= 33,

ANONYMOUS_GTID_LOG_EVENT= 34,

PREVIOUS_GTIDS_LOG_EVENT= 35,

TRANSACTION_CONTEXT_EVENT= 36,

VIEW_CHANGE_EVENT= 37,

XA_PREPARE_LOG_EVENT= 38,

對於使用binlog日誌文件進行數據恢復來說,下面4個事件非常重要:

TABLE_MAP_EVENT = 19, 將數據庫名和表名和表id關聯起來。

WRITE_ROWS_EVENT = 30, INSERT語句使用。

UPDATE_ROWS_EVENT = 31,UPDATE語句使用。

DELETE_ROWS_EVENT = 32,DELETE語句使用。

後面這三種事件處理方式非常類似,都是基於Rows_event,即包含記錄行數據。

1. binlog事件頭部結構

binlog事件具有相同的頭部結構,總共19個字節。下表中偏移和長度均為十進制整數。

偏移

長度

字段

0

4

時間戳

4

1

事件類型

5

4

MySQL server-id

9

4

本事件的長度

13

4

下一個事件的開始位置

17

2

標誌

上面表格中偏移量13長度4字節的字段,在<<MySQL Internals Manual>>(2006)文件中描述如下:

技術分享圖片

事件頭部結構中的這個字段在MySQL Server 5.7.22源代碼中的註釋:

技術分享圖片

事件頭部結構在MyFlash工具的源代碼中定義如下(2019,適用於v4版本的binlog):

技術分享圖片

從後面的分析中可以看到,在MySQL Server 5.17..22版本產生的binlog日誌文件中,認為是下一個事件的開始位置更為合適。這個字段的作用主要是用於在整個文件中快速的遍歷各個事件從而找到特定的事件。

1. binlog字節碼分析的準備工作

本文的目標是通過解析MySQL數據庫的binlog日誌文件的字節碼來了解binlog日誌文件的格式。

目標binlog文件:mysql_binlog.000003

為了分析方便,復制為all.binlog,通過hexdump程序取得十六進制格式的文本文件all.hex,通過mysqlbinlog程序取得對應的sql文件。

[root@101 binlog]# ls -l all.*

-rw-r-----. 1 root root 10015 Sep 21 17:58 all.binlog

-rw-r--r--. 1 root root 49462 Sep 21 17:45 all.hex

-rw-r--r--. 1 root root 36776 Sep 21 17:43 all.sql

1. binlog日誌文件MAGIC代碼。

bin日誌文件的magic代碼的值在MySQL Server 5.7.22源代碼中的定義如下:

技術分享圖片

binlog日誌文件的前面4個字節是固定的magic代碼,內容為“.bin”。

技術分享圖片

1. Format desc事件

每個binlog日誌文件的第1個事件總是Format_desc

mysql> show binlog events in ‘mysql_binlog.000003‘ limit 1\G

*************************** 1. row ***************************

Log_name: mysql_binlog.000003

Pos: 4

Event_type: Format_desc

Server_id: 101

End_log_pos: 123

Info: Server ver: 5.7.22-log, Binlog ver: 4

通過binlog文件的字節碼可以分析第1個事件的內容。

下面通過分析第1個事件的事件頭部結構。

技術分享圖片

時間戳:

mysql> select from_unixtime(0+0x5ba39a5c);

+-----------------------------+

| from_unixtime(0+0x5ba39a5c) |

+-----------------------------+

| 2018-09-20 21:02:20 |

+-----------------------------+

1 row in set (0.00 sec)

事件的字節數大小,以及事件的結束位置,以及下一個事件的開始位置:

mysql> select 0+0x77, 4+0x77 , 0+0x7b;

+--------+--------+--------+

| 0+0x77 | 4+0x77 | 0+0x7b |

+--------+--------+--------+

| 119 | 123 | 123 |

+--------+--------+--------+

1 row in set (0.00 sec)

因此,第1個事件的事件頭部結構的各個字段的值如下:

字段

字節碼

時間戳

5c9aa35b

2018-09-20 21:02:20

事件類型

0f

15

MySQL server-id

65000000

101

本事件的長度

77000000

119

下一個事件的開始位置

7b000000

123

標誌

0000

0

這個事件的事件頭信息與前面show binlog events 的結果是一致的。

show binlog events 的結果中pos是這個事件的事件頭結構的開始位置,即在整個文件中的偏移量,第1個事件,因此偏移量總是4End_log_pos是這個事件的所有數據的最後一個字節之後的那個字節的位置,即下一個事件的事件頭結構的開始位置。

這個事件的長度是119,這個長度包括事件頭結構和事件具體內容兩個部分。

現在需要了解Format Desc事件的內容部分的具體格式:

MySQL Server 5.7.22版本的源代碼中找到了以下的註釋:

技術分享圖片

似乎顯示binlog日誌是v4版本的,但是其中的基類的名字似乎顯示binlog日誌是v3版本的。

技術分享圖片

看到下面這段註釋終於明白了。MySQL Server V5.7.22binlog日誌是V4版本的,只是這個Format_desc 事件是從Start_event_v3派生而來的。

技術分享圖片

至此,Format Desc事件的具體內容的格式已經清楚了:

由於事件的頭部結構的長度固定為19個字節,因此,此處的第1個字段的事件內部偏移為19

事件偏移

長度

字段

19

2

binlog版本號

21

50

Server版本信息

71

4

創建時間戳

75

1

頭部結構的長度

76

N

現在來觀察這個Format Desc事件的具體內容部分。

具體內容部分的開始位置和結束位置如下所示:

mysql> select hex(4+19),hex(4+119-1);

+-----------+--------------+

| hex(4+19) | hex(4+119-1) |

+-----------+--------------+

| 17 | 7A |

+-----------+--------------+

1 row in set (0.01 sec)

即下圖中灰色部分所示區域。

技術分享圖片

計算時間戳的偏移量:

mysql> select hex(4+71);

+-----------+

| hex(4+71) |

+-----------+

| 4B |

+-----------+

1 row in set (0.00 sec)

轉換為human-readable時間:

mysql> select from_unixtime(0x5ba39a5c);

+---------------------------+

| from_unixtime(0x5ba39a5c) |

+---------------------------+

| 2018-09-20 21:02:20 |

+---------------------------+

1 row in set (0.00 sec)

前面介紹的事件頭部結構(19個字節固定長度)對每個事件來說都是相同的結構相同的長度,稱之為common Header

binlog事件的事件相關頭部的長度,事件相關頭部即具體某個事件特有的結構,稱之為Post Header

事件類型的長度數組:

存儲本MySQL Server支持的每一種事件的Post Header Length,即事件相關頭部的長度。前面已經介紹過,總共38種類型的事件,因此這個數組總共更有38個元素,總共占用38個字節。

技術分享圖片

上圖中灰色標記區域即是這個數組的內容。

由於Format Desc事件的事件類型是15,因此這個事件的Post Header Length0x5f,即十進制的95。可以這樣來驗證:

mysql> select 2+50+4+1+38;

+-------------+

| 2+50+4+1+38 |

+-------------+

| 95 |

+-------------+

1 row in set (0.00 sec)

上述元素的各項即Format Desc 事件的事件相關頭部的各個組成部分的長度。

因此,Format Desc事件的具體內容部分的各個字段的值總結如下:

字段

字節碼

binlog版本號

0400

4

Server版本信息

352e372e32322d6c6f6700 .....

5.7.22-log

創建時間戳

5c9aa35b

2018-09-20 21:02:20

頭部結構的長度

13

19

事件類型數組

省略

省略

前面已經了解這個事件的總長度是119個字節,剛剛介紹都是事件的頭部:Common HeaderPost Header,總共95個字節。 可以發現實際數據顯示出多了5個字節:

mysql> select 19+95, 119-(19+95);

+-------+-------------+

| 19+95 | 119-(19+95) |

+-------+-------------+

| 114 | 5 |

+-------+-------------+

1 row in set (0.00 sec)

技術分享圖片

5個字節的具體內容是什麽,稍後介紹。

下面進一步了解一下多出來的5個字節的真正的內容是什麽。

找到了以下這個代碼片段:

技術分享圖片

95個字節之後還寫入了一個字節,這個字節用於指示是否使用校驗碼。這個字節的具體定義如下所示:

技術分享圖片

從前面的字節碼截圖可以看到,此處該值為1,即使用CRC32校驗。 在這個write函數中並沒有填充緊接著的4個字節,猜想有可能在其它地方處理了4個字節。

馬上看到了這個代碼片段:

技術分享圖片

其中定義了一個CRC32的簽名長度,正好4個字節。因此多出來的4個字節有可能是CRC32簽名的結果。

技術分享圖片

至此,Format Desc事件字節碼分析完畢。

Write rows事件將在下一篇博客中介紹。

MySQLbinlog日誌03binlog日誌字節碼解析