230_mysql_binlog结构组成(mysql binlog详解)

网友投稿 1003 2022-05-30

Mysql Binlog event类型

https://dev.mysql.com/doc/internals/en/event-meanings.html

enum Log_event_type { UNKNOWN_EVENT= 0, START_EVENT_V3= 1, QUERY_EVENT= 2, STOP_EVENT= 3, ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT= 6, SLAVE_EVENT= 7, CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10, DELETE_FILE_EVENT= 11, NEW_LOAD_EVENT= 12, RAND_EVENT= 13, USER_VAR_EVENT= 14, FORMAT_DESCRIPTION_EVENT= 15, XID_EVENT= 16, BEGIN_LOAD_QUERY_EVENT= 17, EXECUTE_LOAD_QUERY_EVENT= 18, TABLE_MAP_EVENT = 19, PRE_GA_WRITE_ROWS_EVENT = 20, PRE_GA_UPDATE_ROWS_EVENT = 21, PRE_GA_DELETE_ROWS_EVENT = 22, WRITE_ROWS_EVENT_V1 = 23, UPDATE_ROWS_EVENT_V1 = 24, DELETE_ROWS_EVENT_V1 = 25, INCIDENT_EVENT= 26, HEARTBEAT_LOG_EVENT= 27, IGNORABLE_LOG_EVENT= 28, ROWS_QUERY_LOG_EVENT= 29, WRITE_ROWS_EVENT = 30, UPDATE_ROWS_EVENT = 31, DELETE_ROWS_EVENT = 32, GTID_LOG_EVENT= 33, ANONYMOUS_GTID_LOG_EVENT= 34, PREVIOUS_GTIDS_LOG_EVENT= 35, ENUM_END_EVENT /* end marker */ };

1 常见binlog_event类型

event类型含义

FORMAT_DESCRIPTION_EVENT

每个binlog文件开头的一个event, 记录binlog的版本,数据库版本,创建时间等基本信息

ROTATE_EVENT

1切换新binlog文件:执行FLUSH LOGS语句 or binlog达阈值max_binlog_size意外宕机重启后会新生成binlog

2 切换新的binlog文件的时候,MySQL会在旧的binlog文件中写入一个ROTATE_EVENT,表示新的binlog文件的文件名,以及第一个偏移地址。

3宕机前最后一个binlog不是 ROTATE_EVENT结尾

数据库变更事件

TABLE_MAP_EVENT

TABLE_MAP_EVENT只有在binlog文件是以ROW格式记录的时候,才会使用。binlog中记录的每个更改的记录之前都会有一个对应要操作的表的TABLE_MAP_EVENT。TABLE_MAP_EVENT中记录了表的定义(包括database name,table name,字段定义),并且会将这个表的定义对应于一个数字,称为table_id。设计TABLE_MAP_EVENT类型event的目的是为了当主库和从库之间有不同的表定义的时候,复制仍能进行。如果一个事务中操作了多个表,多行记录,在binlog中会将对多行记录的操作event进行分组,每组行记录操作event前面会出现对应表的TABLE_MAP_EVENT。

QUERY_EVENT

QUERY_EVENT以文本的形式来记录事务的操作

QUERY_EVENT类型的事件通常在以下几种情况下使用:

事务开始时,执行的BEGIN操作。

STATEMENT格式中的DML操作。

ROW格式中的DDL操作。

ROWS_EVENT

对于ROW格式的binlog,所有的DML语句都是记录在ROWS_EVENT中。

ROWS_EVENT分为三种:WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT

对于QUERY_EVENT事件,是以文本形式记录DML操作的。而对于ROWS_EVENT事件,并不是文本形式,所以在通过mysqlbinlog查看基于ROW格式的binlog时,需要指定-vv --base64-output=decode-rows

WRITE_ROWS_EVENT

UPDATE_ROWS_EVENT

DELETE_ROWS_EVENT

在以ROW格式记录的binlog文件中,WRITE_ROWS_EVENT记录了插入的行记录

在以ROW格式记录的binlog文件中,UPDATE_ROWS_EVENT记录了更新的行记录

在以ROW格式记录的binlog文件中,DELETE_ROWS_EVENT记录了删除的行记录

HEARTBEAT_LOG_EVENT

由master发给slave的,让slave知道master还活着。这类事件不会在binlog或relay log中出现。

他们由master的dump事件线程产生,然后直接发给了slave。slave收到后,校验事件内容后,直接抛弃这个事件,而不会写到relay log中

2 event字节解析

在MySQL的发展过程中,一共出现过三个版本的event结构:

v1:在MySQL 3.23中使用

v2:在MySQL4.0.2至4.1中使用

v4:在MySQL5.0及以上版本中使用

3 event组织架构

v4版本的event主要由event header部分和post-header以及variable part部分组成。

event组织架构

event header

是每个event都会有的部分,并且每个event header的格式是相同的,固定为19个字节长度,在event header 中记录了event_length、type_code等信息,可以表示event的长度,event的类型,下一个event的偏移位置等信息,都可以再event header中获取到。

extra_headers

指定了除公共头部外的内容,但是目前版本的binlog格式中,这一部分不存在的

fixed_part & post-header

每个类型的event之间的post-header部分是不相同的,但是同一类型的event占用的post-header

字节数是一样的。每个类型的event占用多少字节为post-header,这个定义在了Format_description_event中

variable part & body

event真实记录具体信息的部分;part有些时候也被称作payload或者body

event字节结构表示如下

timestamp记录的是该事务记录的时间

type_code,记录的是该event的类型,具体的event类型,见上面的Log_event_type

server_id,记录的是执行该event的server的server_id号

event_length,该event的长度,共占多少字节

next_position,下一个event在binlog文件中的偏移位置

flag:标记

extra_headers,额外的头部内容,现在是空的,不存在

fixed part有些时候也被称作post-header

variable part有些时候也被称作payload或者body

event公共头部

从上述的event结构中,可以看到,每个event的header部分的内容结构是一致的,所有的event,都会记录这些信息,这是所有的event的公共头部分

字段

字节数

描述

timestamp

4字节

时间戳

type_code

1字节

记录event类型

server_id

4 字节

记录event生成的MySQL所对应的server_id

event_length

4字节

这个event的字节长度,包括event header

next_position

4字节

下一个event在binlog文件中的偏移位置

flags

2字节

b6 1e 1c 5a //timestamp:小端存储,将16进制转换成10进制为1511792310,将时间戳转换为时间为2017-11-27 22:18:30 1e //type_code:event类型,0x1e转换为10进制为30,查看Log_event_type中,看到30的为WRITE_ROWS_EVENT 0f 27 00 00 //server_id :小端存储,将16进制转换为10进制为9999 31 00 00 00 //event_length :小端存储,将16进制转换为10进制为49 b1 03 00 00 //next_position:小端存储,将16进制转换为10进制为945 00 00 //flags: body部分省略

Format_description_event

Format_description_event是每个binlog文件开头的一个描述信息的event

fixed part (post-header) 部分

字段

字节数

描述

binlog_version

2字节

binlog结构的版本,v1,v2,v4

server_version

50字节

MySQL server的数据库版本

timestamp

4字节

创建该binlog文件的时间,单位为秒

header_length

1字节

指定公共头部的长度,v4版本中这个值一直为19,说明其他所有的event的extra_header部分都是空, extra_header长度为header_length-19

event_post_header_length

variable size跟各个版本支持的event类型总数一致

每个event类型,占用一个字节,表示该event类型post-header部分的长度

Variable part (event-body)部分

字节解析示例 公共头部部分省略 04 00 //binlog_version :v4版本 35 2e 36 2e 33 34 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //mysql server version :16进制转换为ascii之后,值为5.6.34-log 00 00 00 00 //timestamp: 13 //header length :19,说明该版本的event类型公共头部长度都为19,extra_header长度为header_length-19 38 0d 00 08 00 12 00 04 04 04 04 12 00 00 5c 00 04 1a 08 00 00 00 08 08 08 02 00 00 00 0a 0a 0a 19 19 00 //event_post_header_len:各个类型event的post-header部分长度 01 2e ef 23 e2

Rotate_event

当MySQL切换至新的binlog文件的时候,MySQL会在旧的binlog文件中写入一个ROTATE_EVENT,其内容包含新的binlog文件的文件名以及第一个偏移地址。当在数据库中执行FLUSH LOGS语句或者binlog文件的大小超过max_binlog_size参数设定的值就会切换新的binlog文件。

fixed part (post-header) 部分

字段

字节数

描述

next_binlog_po

8字节

下一个binlog文件起始的偏移地址

Variable part (event-body)部分

字段

字节数

描述

next_binlog_filename

variable string

下一个binlog文件的文件名

字节解析示例 公共头部部分省略 04 00 00 00 00 00 00 00 //next_binlog_pos:下一个binlog的起始偏移地址,小端存储,16进制转换为10进制之后为4 6d 79 73 71 6c 2d 62 69 6e 2e 30 30 30 30 30 32 //next_binlog_filename:下一个binlog的文件名,16进制转换为ascii之后,值为mysql-bin.000002 b3 db 0b 9a checksum

Query_log_event

记录更新操作的语句

fixed part (post-header) 部分

字段

字节数

描述

thread_id

230_mysql_binlog结构组成(mysql binlog详解)

4字节

执行语句的线程ID号

exec_time

4字节

语句执行的时间

db_len

1字节

database名的长度

error_code

2字节

错误号

status_vars_len

2字节

在v1和v3版本的event中是没有的,指定状态值的长度

Variable part (event-body)部分

字段

字节数

描述

status_vars

status_vars_len字节

记录状态值,具体的解析见下表

database_name

db_len+1字节

null-terminaled类型的字符串,记录database的名字

query_statement

不定

执行的语句

check_sum

4字节

校验码

status_vars的解析是,一个字节表示状态的类型,在类型之后按照类型不同紧接着不同字节数的状态值,状态的类型对应状态码以及字节数

enum Query_event_status_vars { Q_FLAGS2_CODE= 0, #4字节 Q_SQL_MODE_CODE= 1, #8字节 Q_CATALOG_CODE=2, #第一个字节表示catalog_len,总共catalog_len+2个字节 Q_AUTO_INCREMENT=3, #4字节 Q_CHARSET_CODE=4, #6字节 Q_TIME_ZONE_CODE=5, #第一个字节表示time_zone_len,总共time_zone_len+1字节 Q_CATALOG_NZ_CODE=6, # 第一个字节表示catalog_len,总共catalog_len+1个字节 Q_LC_TIME_NAMES_CODE=7, #2字节 Q_CHARSET_DATABASE_CODE=8, #2字节 Q_TABLE_MAP_FOR_UPDATE_CODE=9, #8字节 Q_MASTER_DATA_WRITTEN_CODE=10, #4字节 Q_INVOKER =11, #包含两部分,一部分是user,一部分是host。user部分,一个字节表示user_len,接着user_len个字节表示user。host部分,一个字节表示host_len,接着host_len个字节表示host Q_UPDATED_DB_NAMES=12, Q_MICROSECONDS =13, 3字节 Q_COMMIT_TS=14, Q_COMMIT_TS2=15, Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP=16 1字节 };

解析二进制文件 公共头部部分省略。。。。 a4 9f 01 00 //thread_id:执行语句的线程号,小端存储,转换为16进制为106404 00 00 00 00 //exec_time:执行语句的时间,小端存储,转化为16进制为0 08 //db_len:database name的长度,转换为10进制为8 00 00 //error_code:错误号,小端存储,转换为10进制为0 2a 00 //status_vars_len:状态值的长度,小端存储,转换为10进制为42,表示后续的42个字节为状态值的内容 //status_vars_len 00 00 00 00 00 01 00 00 20 40 00 00 00 00 06 03 73 74 64 03 02 00 02 00 04 21 00 21 00 53 00 0c 01 67 61 6e 67 73 68 65 6e 00 67 61 6e 67 73 68 65 6e 00 //database_name:数据库名称,null-terminaled string类型 ,转换为字符串为gangshen 696e7365727420696e746f20746573743128606e616d6560292076616c75657328276265696a696e672729 //query_statement:执行的语句,转换为字符串为:insert into test1(`name`) values('beijing') 21 92 37 98//checksum

Rows_query_log_event

在row格式复制模式下,将query以语句形式记录。在5.6.2版本之后,可以通过设置binlog_rows_query_log_events参数来控制在row格式复制模式下是否需要将query语句记录到binlog文件中。

fixed part (post-header) 部分

Variable part (event-body)部分

字段

字节数

描述

str_len

1字节

记录语句长度

statement

str_len字节

对应的语句

checksum

4字节

校验码

解析二进制文件: 公共头部部分省略。。。 2e //str_len:执行语句的长度,转换为10进制为46 696e7365727420696e746f20746573743128606e616d6560292076616c7565732827726f77735f71756572792729 //statement:执行的语句,转换为ascii为insert into test1(`name`) values('rows_query') 8a af 68 dc //check_sum

Table_map_event

TABLE_MAP_EVENT只有在binlog文件是以ROW格式记录的时候,才会使用。binlog中记录的每个更改的记录之前都会有一个对应要操作的表的TABLE_MAP_EVENT。 TABLE_MAP_EVENT中记录了表的定义(包括database name,table name,字段定义),并且会将这个表的定义对应于一个数字,称为table_id。 设计TABLE_MAP_EVENT类型event的目的是为了当主库和从库之间有不同的表定义的时候,复制仍能进行。 如果一个事务中操作了多个表,多行记录,在binlog中会将对多行记录的操作event进行分组,每组行记录操作event前面会出现对应表的TABLE_MAP_EVENT

fixed part (post-header) 部分

字段

字节数

描述

table_id

6字节

操作的表的table_id

flags

2字节

目前版本没有用,都是0,保留给之后的版本使用

Variable part (event-body)部分

字段

字节数

描述

database_name

1个字节表示字符串长度,之后接一个null-terminated类型的字符串

操作的数据库的名称

dtable_name

1个字节表示字符串长度,之后接一个null-terminated类型的字符串

操作的表的名称

column_count

packed integer(1或3或4或9个字节)

对应表中的字段数量

column_type

每个字段占用一个字节,字段类型定义在enum_field_types中

字段类型

metadata_length

packed integer(1或3或4或9个字节)

对应字段的元数据信息的长度

metadata

根据enum_field_type中的定义确定不同字段的元数据,如果某字段类型没有元数据,则不记录

每个字段的元数据信息,比如varchar字段需要记录最长长度

null_bits

int((column_count + 7)/8) 字节

一个bit表示一个字段是否可以为NULL,顺序是:第一个字节的最低位开始向最高位增长,之后第二个字节的最低位开始向最高位增长,以此类推

check_sum

4字节

校验码

CREATE TABLE `test1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

二进制内容解析: 公共头部部分省略 6c 00 00 00 00 00 //table_id :小端存储,16进制转换为10进制为108 01 00 //flag : 08 67 61 6e 67 73 68 65 6e 00 //database_name :1个字节是字符串长度,后接一个null-terminated string 第一个字节表示字符串长度为8,后面内容将16进制转换为ascii字符为gangshen 05 74 65 73 74 31 00 //table_name: 1个字节是字符串长度,后接一个null-terminated string第一个字节表示字符串长度为5,后面内容将16进制转换为ascii字符为test1 02 //columns count :packet integer类型,转换之后,数值为2 表示表中有两个字段 03 0f //column type : 一个字节表示一个字段的类型,字段类型定义在enum enum_field_types ,分别是一个int类型以及一个varchar类型,具体的字段类型及记录格式等信息可以查看《MySQL中Rows_event中字段表示》文档 02 //metadata length : packet integer类型,转换之后,数值为2,表示记录表中的metadata内容占用2个字节 14 00 // :varchar 的max length 因为int没有metadata所以跳过 02 //null_bits :int((column_count + 7) / 8)个字节 一个bit表示一个字段是否可以为null 52 53 4a d9 checksum

Write_rows_log_event

在以ROW格式记录的binlog文件中,Write_rows_log_event记录了插入的行记录

fixed part (post-header) 部分

字段

字节数

描述

table_id

6字节

操作的表的table_id

flags

2字节

目前版本没有用,都是0,保留给之后的版本使用

Variable part (event-body)部分

字段

字节数

描述

var_header

2字节

m_width

packed integer(1或3或4或9个字节)

表中字段数量

before_image

(m_width + 7)/8字节

对应表中的字段数量

after_bitmap_bits

(m_with +7)/8字节

字段值是否为空标记,一个bit表示一个字段是否为NULL,顺序是:第一个字节的最低位开始向最高位增长,之后第二个字节的最低位开始向最高位增长,以此类推

after_column_content

不定

按照顺序每个字段的内容

check_sum

4字节

校验码

建表语句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 插入数据: insert into int_table values(1,11,111,1111,11111,true);

对应Write_rows_log_event使用mysqlbinlog解析 # at 340 #180103 10:21:20 server id 330619 end_log_pos 395 CRC32 0x50177e10 Write_rows: table id 100 flags: STMT_END_F ### INSERT INTO `gangshen`.`int_table` ### SET ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=11 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=111 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 395

公共头部部分省略 64 00 00 00 00 00 //table_id: 小端存储,16进制转换为10进制为100 01 00 //flag: 02 00 //var header length :小端存储,16进制转换为10进制为2 06 //m_width :packet integer,表示表中字段数量 ff //before image: (m_width + 7) / 8字节 c0 //after_bitmap_bits :insert插入之后的记录的NULL标记,表中六个字段,插入的值都不为NULL //after_columns_content:insert插入记录之后的记录值 01 0b 00 6f 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 10 7e 17 50 //checksum

Update_rows_log_event

在以ROW格式记录的binlog文件中,Update_rows_log_event记录了更新的行记录。

fixed part (post-header) 部分

字段

字节数

描述

table_id

6字节

操作的表的table_id

flags

2字节

目前版本没有用,都是0,保留给之后的版本使用

Variable part (event-body)部分

字段

字节数

描述

var_header

2字节

m_width

packed integer(1或3或4或9个字节)

表中字段数量

before_image

(m_width + 7)/8字节

对应表中的字段数量

after_image _image

(m_width + 7)/8字节

对应表中的字段数量

before_bitmap_bits

(m_with+7)/8字节

before_bitmap_bits记录的是update更改之前的记录中,字段值是否为NULL标记,一个bit表示一个字段是否为NULL,顺序是:第一个字节的最低位开始向最高位开始增长,之后第二个字节的最低位开始向最高位增长,以此类推

before_column_content

不定

update更新之前的记录值,按照顺序每个字段的内容

after_bitmap_bits

(m_with +7)/8字节

after_bitmap_bits记录的是update更改之前的记录中,字段值是否为NULL标记,一个bit表示一个字段是否为NULL,顺序是:第一个字节的最低位开始向最高位开始增长,之后第二个字节的最低位开始向最高位增长,以此类推

after_column_content

不定

update更新之后的记录值,按照顺序每个字段的内容

check_sum

4字节

校验码

字节解析示例 建表语句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 插入数据并更新: insert into int_table values(1,11,111,1111,11111,true); update int_table set col2=22,col3=222 where col1=1;

对应Update_rows_log_event使用mysqlbinlog解析 # at 644 #180103 10:41:37 server id 9999 end_log_pos 720 CRC32 0x5576b52f Update_rows: table id 231 flags: STMT_END_F ### UPDATE `gangshen`.`int_table` ### WHERE ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=11 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=111 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### SET ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=22 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=222 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 720

解析二进制文件: 公共头部部分省略。。。 64 00 00 00 00 00 //table_id: 小端存储,16进制转换为10进制为100 01 00 //flag: 02 00 //var header length :小端存储,16进制转换为10进制为2 06 //m_width :packet integer,表示表中字段数量 ff //before image: (m_width + 7) / 8字节 ff //after image: (m_width + 7) / 8字节 c0 //before_bitmap_bits :update更新之前记录中NULL标记,表中六个字段,值都不为NULL //before_column_content接下来是update更新之前记录的值 01 0b 00 6f 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 c0 //after_bitmap_bits :update更新之后记录中NULL标记,表中六个字段,值都不为NULL //after_column_content接下来是update更新之前记录的值 01 16 00 de 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 16 a3 de bb //checksum

Delete_rows_log_event

在以ROW格式记录的binlog文件中,Delete_rows_log_event记录了删除的行记录。

fixed part (post-header) 部分

字段

字节数

描述

table_id

6字节

操作的表的table_id

flags

2字节

目前版本没有用,都是0,保留给之后的版本使用

Variable part (event-body)部分

字段

字节数

描述

var_header

2字节

m_width

packed integer(1或3或4或9个字节)

表中字段数量

after_image _image

(m_width + 7)/8字节

对应表中的字段数量

before_bitmap_bits

(m_with+7)/8字节

before_bitmap_bits记录的是update更改之前的记录中,字段值是否为NULL标记,一个bit表示一个字段是否为NULL,顺序是:第一个字节的最低位开始向最高位开始增长,之后第二个字节的最低位开始向最高位增长,以此类推

before_column_content

不定

delete删除之前的记录值,按照顺序每个字段的内

check_sum

4字节

校验码

建表语句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 删除数据: delete from int_table where col1=1;

对应Delete_rows_log_event使用mysqlbinlog解析 # at 320 #180103 14:24:54 server id 330619 end_log_pos 375 CRC32 0xce4818b2 Delete_rows: table id 100 flags: STMT_END_F ### DELETE FROM `gangshen`.`int_table` ### WHERE ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=22 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=222 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 375

解析二进制文件: 公共头部部分省略 64 00 00 00 00 00 //table_id: 小端存储,16进制转换为10进制为100 01 00 //flag: 02 00 //var header length :小端存储,16进制转换为10进制为2 06 //m_width :packet integer,表示表中字段数量 ff //after image: (m_width + 7) / 8字节 c0 //before_bitmap_bits :delete删除之前的记录的NULL标记,表中六个字段,值都不为NULL //before_columns_content:delete删除记录之前的记录值 01 16 00 de 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 10 7e 17 50 //checksum

Xid_event

表示支持内部XA的存储引擎上的事务提交。正常的事务是通过QUERY_EVENT来发送一个BEGIN语句并且通过QUERY_EVENT来发送一个COMMIT语句(如果事务回滚则发送的是ROLLBACK)实现

fixed part (post-header) 部分

Variable part (event-body)部分

字段

字节数

描述

xid

8字节

无符号数

after_image _image

(m_width + 7)/8字节

对应表中的字段数量

# at 1691 #180103 15:30:45 server id 330619 end_log_pos 1722 CRC32 0x8816181c Xid = 2698 COMMIT/*!*/; # at 1722

解析二进制文件: 公共头部部分省略... 8a 0a 00 00 00 00 00 00 //xid,因为是小端存储,所以实际为0x 00 00 00 00 00 00 0a 8a,转换为10进制为2698 1c 18 16 88 //check_sum

Gtid_log_event

开启GTID模式的场景下,每次事务commit提交时,MySQL会在binlog中事务开始写入一个Gtid_log_event,记录该事务的GTID事务号。

fixed part (post-header) 部分

字段

字节数

描述

commit_flag

1字节

标记事务是否提交,非0为已提交,为0表示,事务未提交

sid

16字节

记录GTID中uuid的部分(不记录‘-’),每1个字节表示uuid中2个字符

gno

8字节

小端存储,GTID中的事务号部分

Variable part (event-body)部分

字段

字节数

描述

checksum        4

4字节

校验码

字节解析示例 使用mysqlbinlog工具解析binlog文件 # at 191 #180109 18:31:08 server id 330619 end_log_pos 239 CRC32 0xd20330e8 GTID [commit=yes] SET @@SESSION.GTID_NEXT= '89fbcea2-da65-11e7-a851-fa163e618bac:5'/*!*/; # at 239 解析二进制文件: 公共头部部分省略。。。。 01 //commit_flag:标记事务是否已提交,表示已提交 89 fb ce a2 da 65 11 e7 a8 51 fa 16 3e 61 8b ac //sid:GTID中uuid部分,转换为uuid为89fbcea2-da65-11e7-a851-fa163e618bac 05 00 00 00 00 00 00 00 //gno:GTID中的事务号,小端存储,转换为10进制为5 e8 30 03 d2 //checksum

Previous_gtid_log_event

在开启GTID的模式下,每个binlog文件开始会记录一个Previous_gtid_log_event,Previous_gtid_log_event中会包含当前binlog之前所有binlog中的GTID集合

fixed part (post-header) 部分

字段

字节数

描述

n_sids

8字节

小端存储,记录之后有几个GTID中的uuid号

sid

16字节

记录GTID中uuid的部分(不记录‘-’),每1个字节表示uuid中2个字符

n_intervals

8字节

记录每个sid对应有几个间隔,指的是事务号间隔

start

8字节

每个事务号间隔中的起始事务号

end

8字节

每个事务号间隔中的结束事务号+1

Variable part (event-body)部分

字段

字节数

描述

checksum        4

4字节

校验码

字节解析示例 使用mysqlbinlog工具解析binlog文件 # at 120 #180111 14:10:27 server id 330619 end_log_pos 279 CRC32 0x94a92478 Previous-GTIDs # 89fbcea2-da65-11e7-a851-fa163e618bac:1-5:999:1050-1052, # aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-2:5-7 DELIMITER ; 解析二进制文件: 公共头部部分省略。。。 02 00 00 00 00 00 00 00 //n_sids:记录之后有几个GTID中的uuid号,小端存储,转换为10进制为2,表后后续有2个uuid号 89 fb ce a2 da 65 11 e7 a8 51 fa 16 3e 61 8b ac //sid:GTID中的uuid号转换为uuid为89fbcea2-da65-11e7-a851-fa163e618bac 03 00 00 00 00 00 00 00 //n_intervals:对应的sid中中对应几个事务号间隔,小端存储,转换为10进制为3,表示有3个事务号间隔 01 00 00 00 00 00 00 00 //start:事务号间隔中的起始事务号,小端存储,转换为10进制为1 06 00 00 00 00 00 00 00 //end:事务号间隔中的结束事务号+1,小端存储,转换为10进制为6,实际的间隔结束事务号为5 e7 03 00 00 00 00 00 00 //start:事务号间隔中的起始事务号,小端存储,转换为10进制为999 e8 03 00 00 00 00 00 00 //end:事务号间隔中的结束事务号+1,小端存储,转换为10进制为1000,实际的间隔结束事务号为999 1a 04 00 00 00 00 00 00 //start:事务号间隔中的起始事务号,小端存储,转换为10进制为1050 1d 04 00 00 00 00 00 00 //end:事务号间隔中的结束事务号+1,小端存储,转换为10进制为1053,实际的间隔结束事务号为1052 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa //sid:GTID中的uuid号转换为uuid为aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 02 00 00 00 00 00 00 00 //n_intervals:对应的sid中中对应几个事务号间隔,小端存储,转换为10进制为2,表示有2个事务号间隔 01 00 00 00 00 00 00 00 //start:事务号间隔中的起始事务号,小端存储,转换为10进制为1 03 00 00 00 00 00 00 00 //end:事务号间隔中的结束事务号+1,小端存储,转换为10进制为3,实际的间隔结束事务号为2 05 00 00 00 00 00 00 00 //start:事务号间隔中的起始事务号,小端存储,转换为10进制为5 08 00 00 00 00 00 00 00 //end:事务号间隔中的结束事务号+1,小端存储,转换为10进制为8,实际的间隔结束事务号为7 78 24 a9 94 //checksum

Anonymous_gtid_log_event

MySQL在binlog中记录每一个匿名事务之前会记录一个Anonymous_gtid_log_event表示接下来的事务是一个匿名事务。

注意:因为在5.6.34中并不会产生Anonymous_gtid_log_event,所以以下内容是基于5.7.19版本解析

fixed part (post-header) 部分

字段

字节数

描述

gtid_flags

1字节

记录binlog格式,如果gtid_flags值为1,表示binlog中可能有以statement方式记录的binlog,如果为0表示,binlog中只有以row格式记录的binlog

sid

16字节

记录GTID中uuid的部分(不记录‘-’),每1个字节表示uuid中2个字符

gno

8字节

GTID中的事务号部分

logical_timestamp_typecode

1字节

判断是否有last_commit和sequence_no,在logical_tmiestamp_typecode=2的情况下,有last_commit和sequence_no

last_commit

8字节

上次提交的事务号

sequence_no

8字节

本次提交的序列号

Variable part (event-body)部分

字段

字节数

描述

checksum        4

4字节

校验码

字节解析示例 使用mysqlbinlog工具解析binlog文件 #180109 10:53:54 server id 9999 end_log_pos 5681 CRC32 0x46be0639 Anonymous_GTID last_committed=20 sequence_number=21 rbr_only=yes /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 5681 解析二进制文件: 公共头部部分省略。。。 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //sid: 00 00 00 00 00 00 00 00 //gno: 02 //logical_timestamp_typecode:判断是否有last_commit和sequence_no,在logical_tmiestamp_typecode=2的情况下,有last_commit和sequence_no,所以这边的话,后续有last_commit和sequence_no部分的内容 14 00 00 00 00 00 00 00 //last_commit:上次提交的事务号,小端存储,转换为10机制为20 15 00 00 00 00 00 00 00 //sequence_no:本次提交的序列号,小端存储,转换为10进制为21 39 06 be 46 //checksum:校验码

MySQL 数据库

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:23篇大数据系列(一)java基础知识全集(2万字干货,建议收藏)
下一篇:Redis Cluster集群原理+三主三从交叉复制实战+故障切换(十)(redis的五种数据类型)
相关文章