MySQL Binlog 文件格式解析(PREVIOUS_GTIDS_LOG_EVENT)

MySQL Binlog文件开头4字节固定为magic number,跟在magic number之后的第一个event通常是格式描述event(FORMAT_DESCRIPTION_EVENT),它记录了一些重要的元数据,比如event header的长度,每种event类型data部分固定长度的大小等等。Binlog event类型大概有40种,本文将介绍另外一种类型的event:PREVIOUS_GTIDS_LOG_EVENT,它记录了上一个binlog文件结束时执行到的gtid集合,通常这个event跟在格式描述event之后,如下图:

mysql> show binlog events in ‘mysql-bin.000002’;
+—————-+———–+————-+——————————————————————–+
| Event_type     | Server_id | End_log_pos | Info                                                               |
+—————-+———–+————-+——————————————————————–+
| Format_desc    |        10 |         123 | Server ver: 5.7.19-17-debug-log, Binlog ver: 4                     |
| Previous_gtids |        10 |         194 | b0d850c2-dbd0-11e9-90c3-080027b8bded:1-53                          |
| Gtid           |        10 |         259 | SET @@SESSION.GTID_NEXT= ‘b0d850c2-dbd0-11e9-90c3-080027b8bded:54’ |
| Query          |        10 |         346 | flush privileges                                                   |
+—————-+———–+————-+——————————————————————–+
从以上示例可以看出Previous_gtids紧接在Format_desc之后,记录了上一个binlog文件结束时的gtid集合。
PREVIOUS_GTIDS_LOG_EVENT 格式解析:
event header 结构解析:
  • timestamp:时间戳,表示该event的生成时间,占用4个字节
  • type_code:event类型,占用1个字节
  • server_id:生成event的server_id,占用4个字节
  • event_length:event的大小,占用4个字节
  • next_position:下一个event的位置,占用4个字节
  • flags:event flags,占用2个字节
PREVIOUS_GTIDS_LOG_EVENT 对应的type_code为 35。
event data结构解析:
  • sid数量,占用8个字节。比如:b0d850c2-dbd0-11e9-90c3-080027b8bded:1-123,c1132ab1-e9be-11e9-a9d7-fa163ec9e7c2:1-6224,有两个server_uuid,因此sid数量为2
  • sid值,占用16字节,比如:b0d850c2-dbd0-11e9-90c3-080027b8bded,占用16字节
  • sid对应的gtid段的数量,占用8字节。比如:b0d850c2-dbd0-11e9-90c3-080027b8bded:1-123:150-158,看最后的数字1-123:150-158,有两段gtid值,所以sid对应的gtid段的数量为2
  • sid对应的gtid段的起始值,占用8字节,比如:1-123,起始值为1
  • sid对应的gtid段的结束值,占用8字节,比如:1-123,结束值为123
  • 如果有多个段,依次解析
  • 如果有多个sid,依次解析
  • 最后4字节,是这个binlog event的crc32检验值
一个完整的 PREVIOUS_GTIDS_LOG_EVENT event二进制示例,如下:
[root@host ~]# hexdump -C -s 123 -n 71  /data/mysql/data_5.7.19/mysql-bin.000002
0000007b  44 d9 2a 5e 23 0a 00 00  00 47 00 00 00 c2 00 00   |D.*^#….G……|
0000008b  00 80 00 01 00 00 00 00  00 00 00 b0 d8 50 c2 db   |………….P..|
0000009b  d0 11 e9 90 c3 08 00 27  b8 bd ed 01 00 00 00 00   |…….’……..|
000000ab  00 00 00 01 00 00 00 00  00 00 00 36 00 00 00 00   |………..6….|
000000bb  00 00 00 bd de dc f1
  • 1~19字节是event header
  • 20~27字节是sid数量,值为1
  • 28~43字节是sid值,为b0d850c2dbd011e990c3080027b8bded
  • 44~51字节是gtid段的数量,值为1
  • 52~59字节是gtid段的起始值,值为1
  • 60~67字节是gtid段的结束值,值为54
  • 68~71字节是整个event的crc32检验值
注意:
从MySQL的show binlog events 解析出的Previous_gtids值为 b0d850c2-dbd0-11e9-90c3-080027b8bded:1-53,实际从MySQL binlog文件中记录的值为 b0d850c2-dbd0-11e9-90c3-080027b8bded:1-54,不知道是MySQL的Bug还是有意为之。
最后:
本文案例涉及的MySQL版本、配置相关信息如下:
  • MySQL Server 5.7.19
  • binlog_format:ROW
  • binlog_row_image:FULL
  • gtid_mode:ON

发表评论