MySQL Binlog 文件格式解析(XID_EVENT)

1. XID_EVENT 是什么?

MySQL Binlog 文件由 event 组成,event 有不同的类型,本文介绍的 XID_EVENT 表示一个事务的提交操作。

举个例子,执行一条事务,然后查看这个事务生成的 Binlog event,如下:

事务 SQL:

begin;
insert into t1 select 1,1;
commit;

生成的 Binlog Event:

mysql> show binlog events in 'mysql-bin.000003';
+------------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                |
+------------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------+
| mysql-bin.000003 |   4 | Format_desc    |        10 |         123 | Server ver: 5.7.19-17-debug-log, Binlog ver: 4                      |
| mysql-bin.000003 | 123 | Previous_gtids |        10 |         194 | b0d850c2-dbd0-11e9-90c3-080027b8bded:1-387                          |
| mysql-bin.000003 | 194 | Gtid           |        10 |         259 | SET @@SESSION.GTID_NEXT= 'b0d850c2-dbd0-11e9-90c3-080027b8bded:388' |
| mysql-bin.000003 | 259 | Query          |        10 |         329 | BEGIN                                                               |
| mysql-bin.000003 | 329 | Table_map      |        10 |         373 | table_id: 154 (db.t1)                                               |
| mysql-bin.000003 | 373 | Write_rows     |        10 |         417 | table_id: 154 flags: STMT_END_F                                     |
| mysql-bin.000003 | 417 | Xid            |        10 |         448 | COMMIT /* xid=3247 */                                               |
+------------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------+
7 rows in set (0.00 sec)

其中 Event_type 为 Xid 的 event 就是本文要介绍的 XID_EVENT,本文涉及的 MySQL 源码版本为 5.7.19。

2. XID_EVENT 格式

XID_EVENT 属于控制类的 event,在源码文件 libbinlogevents/src/control_events.cpp 中,看到如下解析 XID_EVENT 的一段代码,实际上这个 event 只存储了事务提交的 ID,这个 ID 使用 8 字节存储,代码如下:

Xid_event::
Xid_event(const char* buf,
          const Format_description_event *description_event)
  :Binary_log_event(&buf, description_event->binlog_version,
                    description_event->server_version)
{
  //buf is advanced in Binary_log_event constructor to point to
  //beginning of post-header
  /*
   We step to the post-header despite it being empty because it could later be
   filled with something and we have to support that case.
   The Variable Data part begins immediately.
  */
  buf+= description_event->post_header_len[XID_EVENT - 1];
  memcpy((char*) &xid, buf, 8);
}

因此,XID_EVENT 结构如下:

event header(19字节)
event data(即xid,8字节)
event checksum(4字节)
  • event header 格式是固定的,大小为 19 字节,参见:MySQL Binlog文件格式解析,其中 event type 值为 XID_EVENT,也就是 16。
  • event data 存储的是 xid 值,即事务提交 ID,占用 8 个字节。
  • event checksum,4 字节,checksum 校验码,每个 event 都会有。

使用 hexdump 解析 binlog 文件看看是不是符合这个结构。

根据前面 show binlog events in 'mysql-bin.000003'; 的输出,查找到 Xid 起始位置为 417,结束位置为 448,也就是说这个 event 占用 31 个字节,使用 hexdump 解析,命令如下:

hexdump -C -s 417 -n 31 mysql-bin.000003

[root@localhost data_5.7.19]# hexdump -C -s 417 -n 31 mysql-bin.000003
000001a1  72 3a 5c 5f 10 0a 00 00  00 1f 00 00 00 c0 01 00  |r:\_............|
000001b1  00 00 00 af 0c 00 00 00  00 00 00 25 9b ba 89     |...........%...|
000001c0

以上结果可以看到,前 19 个字节为 event header,其中 event_type 为 第 5 个字节,0x10,也就是 16,确实是 XID_EVENT。中间 8 个字节为 Xid,最后 4 个字节为 event 的 checksum值。

文章评论

0条评论