您的位置:首页 > 数据库 > MySQL

MySQL二进制日志分析-TABLE_MAP_EVENT

2019-10-25 11:40 1776 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/Li_Xiang_996/article/details/102740081

TABLE_MAP_EVENT用于描述即将发生数据变化的表的结构。当用户提交一条修改语句时(如, insert, update, delete),MySQL会产生2个Binlog事件: 第一个就是TABLE_MAP_EVENT,用于描述改变对应表的结构(表名, 列的数据类型等信息);紧接着的是ROWS_EVENT,用于描述对应表的行的实际变化值,后续会继续介绍。

先看TABLE_MAP_EVENT的官方定义:The TABLE_MAP_EVENT defines the structure if the tables that are about to be changed.

post-header:
if post_header_len == 6 {
4              table id
} else {
6              table id
}
2              flags
payload:
1              schema name length
string         schema name
1              [00]
1              table name length
string         table name
1              [00]
lenenc-int     column-count
string.var_len [length=$column-count] column-def
lenenc-str     column-meta-def
n              NULL-bitmask, length: (column-count + 8) / 7

1. table id

用于唯一标识一个表的结构,table id是MySQL自动递增分配的。需要注意的是,table id唯一标识的是一个表结构,而不是实际的数据库表。如,一个普通表tpcc.my_test1, 如果在MySQL实例运行期间,没有发生结构变化(DML),那么它的table id就不会变化;但结构发生变化后,会生成新的TABLE_MAP_EVENT,并且使用新的table id标识。

table id是数值类型,根据TABLE_MAP_EVENT的post_header的长度不同占用的字节数也不同,如果post_header的长度为6,那么table_id占用4个字节,否者占6个字节。post_header的长度可以通过前面提到的FORMAT_DESCRIPTION_EVENT获取,这里不赘诉了。

2.flags

占2个字节,保留给未来使用,不需要关心。

3. schema length and name

这里记录了对应表的schema名,首先通过1个字节记录schema名的长度,然后根据长度,就可以获取schema名,并以null[0x00]结尾。

4.table length and name

这里记录了对应表的表名,首先通过1个字节记录表名的长度,然后根据长度,就可以获取表名,并以null[0x00]结尾。

5. column-count

记录了对应表有多少列,lenenc-int类型,也就是Length-Encoded-Integer,可以参考文档https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::LengthEncodedInteger。

简单来说,是一种可变长的存储数值的协议,具体实现来说:

根据第一个字节的数值来确定该数值的存储字节数:
如果第一个字节数值小于0xfb,则该数值通过1个字节存储;
如果第一个字节数值等于0xfc,则该数值通过2个字节存储;
如果第一个字节数值等于0xfd,则该数值通过3个字节存储;
如果第一个字节数值等于0xfe,则该数值通过8个字节存储;
先读取第一个字节,根据第一个字节的值,来获取column-count有多少个字节。

6. column-def

记录了表的列的类型,每一列占1个字节,总共column-count个字节。如:
0x04: 对应MYSQL_TYPE_FLOAT,
0x05: 对应MYSQL_TYPE_DOUBLE,
0xfc: 对应MYSQL_TYPE_BLOB等。

7. column_meta_def

记录了表的列的类型的元数据(通常为列的长度和精度),有些列类型没有元数据,有些类型有元数据,根据类型不同,有的用1个字节记录,有的用2个字节记录。列的元数据解析列值至关重要。

如: MYSQL_TYPE_NEWDECIMAL(0xf6)有2个字节的元数据,第一个字节用于记录长度(precision), 第二个字节用于记录精度(scale):
decimal(8,2) meta_def = 0x0802
如: MySQL 5.6.4引入新的日期时间类型:TIME2, TIMESTAMP2, and DATETIME2, 在新类型中引入了"fractional seconds part - FSP",可以记录精度可以小于秒级,其中"FSP"的长度就记录在1个字节的元数据中:
timestamp(3) meta_def =0x03

8. NULL-bitmask

记录字段是否可以为空,通过位图方式记录,1个bit代表一个字段。

9. Option Mea Data

这是8版本后新增加的部分,根据MySQL的binlog_row_metadata的值,记录了列更多额外的信息,这里不做介绍,可以参考BinlogMiner的代码。

TABLE_MAP_EVENT的具体代码实现可以参考:
https://github.com/Li-Xiang/BinlogMiner/blob/master/src/org/littlestar/mysql/binlog/event/body/impl/TableMapEventBody.java

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: