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 的一点注意:
  1. binlog中存储的表结构信息,只有字段类型,没有字段名称。
  2. binlog中存储的整型,没有signed或者unsigned信息,同样使用mysqlbinlog解析也无法分辨出整型值是否有符号。

发表评论