MySQL Binlog 文件格式解析(TABLE_MAP_EVENT)
基于ROW格式的MySQL Binlog在记录DML语句的数据时,总会先写入一个table_map_event,这种类型的event用于记录表结构相关元数据信息,比如数据库名称,表名称,表的字段类型,表的字段元数据等等,下面将详细介绍table_map_event的结构。
本文案例涉及的MySQL版本及配置信息:
- MySQL Server 5.7.19
- binlog_format:ROW
- binlog_row_image:FULL
一、table_map_event结构图:
结构名称 | 占用字节数 | 描述 |
event header | 19字节 | event头信息,其中event type类型为TABLE_MAP_EVENT,值为19 |
table id | 6字节 | table id |
flags | 2字节 | flags |
schema name length | 1字节 | 数据库名称长度,假设为n |
schema name | n+1字节 | 数据库名称,实际长度为n,加上最后一个字节0,总长度为n+1 |
table name length | 1字节 | 表名称长度,假设为m |
table name | m+1字节 | 表名称,实际长度为m,加上最后一个字节0,总长度为m+1 |
field count | 1或3或4字节 | 字段数量,占用1,3,4字节不等,根据具体数量决定 |
field types | field count 个字节 | 字段类型,每个类型占用1个字节 |
metadata | 长度不定 | 表字段元数据,长度不定,也可能没有,由具体的表字段类型决定,通常不定长字段和浮点型字段都会有metadata |
field is null | 占用字节数为:(field_count + 7) / 8 | 表示表中哪些字段可以为空,每个字段使用1个bit表示 |
二、字段类型:
MySQL表的字段类型是一个枚举类型,在binlog中,一个类型使用一个字节就能存下,如下:
typedef enum enum_field_types {
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
MYSQL_TYPE_TIMESTAMP2,
MYSQL_TYPE_DATETIME2,
MYSQL_TYPE_TIME2,
MYSQL_TYPE_JSON=245,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
MYSQL_TYPE_MEDIUM_BLOB=250,
MYSQL_TYPE_LONG_BLOB=251,
MYSQL_TYPE_BLOB=252,
MYSQL_TYPE_VAR_STRING=253,
MYSQL_TYPE_STRING=254,
MYSQL_TYPE_GEOMETRY=255
} enum_field_types;
三、metadata元数据分析:
不同类型的字段,其metadata大小和意义也不相同。
字段名称 | metadata大小 | 描述 |
MYSQL_TYPE_TINY MYSQL_TYPE_SHORT MYSQL_TYPE_INT24 MYSQL_TYPE_LONG MYSQL_TYPE_LONGLONG MYSQL_TYPE_YEAR MYSQL_TYPE_DATE | metadata为空 | 占用固定大小的类型,其metadata通常为空。 |
MYSQL_TYPE_FLOAT | metadata 1字节 | 值固定为4,即float占用的字节数 |
MYSQL_TYPE_DOUBLE | metadata 1字节 | 值固定为8,即double占用的字节数 |
MYSQL_TYPE_NEWDECIMAL | metadata 2字节 | 第1个字节表示精度,即小数点前的位数 第2个字节表示小数点后的位数 |
MYSQL_TYPE_VARCHAR | metadata 2字节 | 表示占用的字节数(不是字符数) |
MYSQL_TYPE_STRING MYSQL_TYPE_ENUM MYSQL_TYPE_SET | metadata 2字节 | 在binlog中,char,set, enum 三种类型都使用MYSQL_TYPE_STRING表示,对于set和enum metadata第1个字节表示其真实的字段类型,第2个字节表示数据占用的字节数。char类型的表示略有不同。 |
MYSQL_TYPE_BLOB MYSQL_TYPE_JSON MYSQL_TYPE_GEOMETRY | metadata 1字节 | 值为字节数,即使用多少个字节来表示blob类型数据占用的大小。text,blob,json,geometry在binlog中都以blob类型来表示。 |
MYSQL_TYPE_BIT | metadata 2字节 | 表示bit的位数,metadata第1个字节为位数除8的整数,metadata第2个字节为位数对8取的余数。 |
MYSQL_TYPE_TIME2 MYSQL_TYPE_TIMESTAMP2 MYSQL_TYPE_DATETIME2 | metadata 1字节 | 表示秒后面的位数,比如20:20:20.123,metadata值为3 |
最后,关于binlog table_map_event 的一点注意:
- binlog中存储的表结构信息,只有字段类型,没有字段名称。
- binlog中存储的整型,没有signed或者unsigned信息,同样使用mysqlbinlog解析也无法分辨出整型值是否有符号。
文章评论