基于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解析也无法分辨出整型值是否有符号。