MySQL二进制日志分析-TABLE_MAP_EVENT

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值