[pymysqlbinlog] QUERY_EVENT & XID_EVENT 解析Binlog获取DDL和commit
导读
本来准备写pymysqlbinlog的接口了, 发现还没解析XID和QUERY_EVENT… 先补上吧.
XID EVENT
xid event比较简单, 就event_header + XID 就没了…
xid是啥呢? 就当作是标识事务的就行, 重启之后会重置.
| 对象 | 大小 | 描述 |
|---|---|---|
| XID | 8 | xid |
QUERY EVENT
query event是记录DDL语句的. 虽然我们无法回滚DDL语句, 但还是要解析的.
格式如下
| 对象 | 大小(字节) | 描述 |
|---|---|---|
| thread_id | 4 | 标识客户端的连接ID的 (PROCESSLIST_ID) |
| query_exec_time | 4 | 执行时间(秒) |
| db_len | 1 | 数据库名字长度 |
| error_code | 2 | 错误码 |
| status_vars_len | 2 | 状态值的长度 |
| status_vars | status_vars_len | 状态值(大概20个KEY) |
| dbname | db_len | 数据库名(x00结尾) |
| query | 剩下的字节 | DDL语句 |
看起来还是比较简单的.
其实解析到这里就差不多了, 毕竟已经拿到了的DDL语句.
但还有个status vars 在那占了个大头, 我们还是来解析看吧.
STATUS VARS
官方注释信息存在部分问题, 我们以实际源码为主
STATUS VARS 格式为 KEY-VALUE格式, KEY标识哪种类型, VALUE为该类型的值. 只能一个个按顺序读.
| KEY | KEY-NAME | VALUE大小 | 描述 |
|---|---|---|---|
| 0 | Q_FLAGS2_CODE | 4 | flags |
| 1 | Q_SQL_MODE_CODE | 8 | 就是sql_mode, 在之前连接协议的时候讲过(https://cloud.tencent.com/developer/article/2243951) |
| 2 | Q_CATALOG_CODE | 1 | catalog |
| 3 | Q_AUTO_INCREMENT | 2+2 | auto_increment_increment 和auto_increment_offset |
| 4 | Q_CHARSET_CODE | 2+2+2 | character_set_client collation_connection collation_server |
| 5 | Q_TIME_ZONE_CODE | 1+n | 时区信息, 如果有长度,则有记录时区信息,很多信息都是这样的,就不再重复说了. |
| 6 | Q_CATALOG_NZ_CODE | 1+n | |
| 7 | Q_LC_TIME_NAMES_CODE | 2 | lc_time_names_number |
| 8 | Q_CHARSET_DATABASE_CODE | 2 | 数据库字符集 |
| 9 | Q_TABLE_MAP_FOR_UPDATE_CODE | 8 | table_map_for_update |
| 10 | Q_MASTER_DATA_WRITTEN_CODE | x | 占位的 |
| 11 | Q_INVOKER | 1+n, 1+n | user, host |
| 12 | Q_UPDATED_DB_NAMES | 1+n | 库名 |
| 13 | Q_MICROSECONDS | 3 | |
| 14 | Q_COMMIT_TS | ||
| 15 | Q_COMMIT_TS2 | ||
| 16 | Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP | 1 | explicit_defaults_for_timestamp |
| 17 | Q_DDL_LOGGED_WITH_XID | 8 | 和XID_EVENT的XID一样, 所以query event不需要XID EVENT |
| 18 | Q_DEFAULT_COLLATION_FOR_UTF8MB4 | 2 | 排序规则 |
| 19 | Q_SQL_REQUIRE_PRIMARY_KEY | 1 | sql_require_primary_key |
| 20 | Q_DEFAULT_TABLE_ENCRYPTION | 1 | default_table_encryption |
看起来一大堆… 实际上没多少有用信息, 字符集NO对应的实际值 需要去数据库里查一下 select * from information_schema.COLLATIONS
(u1@127.0.0.1) [(none)]> select * from information_schema.COLLATIONS where id=255;
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
| COLLATION_NAME | CHARACTER_SET_NAME | ID | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
| utf8mb4_0900_ai_ci | utf8mb4 | 255 | Yes | Yes | 0 | NO PAD |
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
1 row in set (0.00 sec)
测试
XID EVENT测试
这个比较简单, 就一个XID
![[pymysqlbinlog] QUERY_EVENT & XID_EVENT 解析Binlog获取DDL和commit-每日运维网 [pymysqlbinlog] QUERY_EVENT & XID_EVENT 解析Binlog获取DDL和commit-每日运维网](https://img.mryunwei.com/uploads/2024/04/20240430193758561.png)

QUERY EVENT测试
query event有很多属性, 但是mysqlbinlog没有解析… 所以我们能对比的信息还是很少…
![[pymysqlbinlog] QUERY_EVENT & XID_EVENT 解析Binlog获取DDL和commit-每日运维网 [pymysqlbinlog] QUERY_EVENT & XID_EVENT 解析Binlog获取DDL和commit-每日运维网](https://img.mryunwei.com/uploads/2024/04/20240501033759892.png)

我们解析的信息也都对得上. 说明解析正确.
到此 binlog event基本上算是解析完了. 后面就是写接口和测试了.