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值。