《Mysql Binlog事件结构》要点:
本文介绍了Mysql Binlog事件结构,希望对您有用。如果有疑问,可以联系我们。
这个部分描述了事件被写入binlog或者delay log中的属性.所有的事件有相同的整体结构,也就是包括事件头和事件数据:
+===================+| event header |+===================+| event data |+===================+
具体的内容随着Mysql版本的升级而不同,这导致了binlog格式的不一致:
v1:用于3.23版本
v3:用于4.0.2到4.1版本
v4:用于5.0及以上版本
v2的格式用于4.0.x的版本中,但是已经过期了,并且不再支持了.
有些变乱的结构随着版本没有改变,而有些与版本有关.在所有的版本中,不同类型的变乱在数据部分的结构不一样.
日志文件的第一个事件是特殊的.他是个符号事件,包括binlog版本和服务器版本.符号事件中的信息让程序能够决定日志文件的格式,这样剩余的事件内容才能被正确的解析出来.
下面说明下不同版本的binlog格式:
v1变乱结构:
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 |+=====================================+| event | fixed part 13 : y || data +----------------------------+| | variable part |+=====================================+
头长度=13字节,数据长度=(变乱长度-13)字节,y与变乱类型有关.
v3变乱结构
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 || +----------------------------+| | next_position 13 : 4 || +----------------------------+| | flags 17 : 2 |+=====================================+| event | fixed part 19 : y || data +----------------------------+| | variable part |+=====================================+
头长度=19字节,数据长度=(变乱长度-19)字节,y与变乱类型有关.
v4变乱结构
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 || +----------------------------+| | next_position 13 : 4 || +----------------------------+| | flags 17 : 2 || +----------------------------+| | extra_headers 19 : x-19 |+=====================================+| event | fixed part x : y || data +----------------------------+| | variable part |+=====================================+
头长度=x字节,数据长度=(变乱长度-x)字节,固定数据部分长度=y字节,变量数据程度=(变乱长度-(x+y))字节.x由FDE(格式描述变乱format description event)header_length给出.当前来说,x=19,所以extra_headers字段是空的.
y和变乱类型有关,也是由FDE给出的.fixed-part的长度对于同一个变乱类型是一样的,但是不同的变乱类型是不一样的.
fixed-part有时候指的是post-header,变量部分有时候指的是payload或者body.
一、变乱内容-写入约定
变乱内容的写入约定如下:
数字是依照地位优先的格式写入的(最不重要字节有限),除非显式表示
表示位置或长度的值以字节形式写入,并且是无符号的
有些数字是以封包整数的形式写入的,这个格式后面再详细说明
字符串有以下几种格式:
字符串可能写入一个固定长度域中,右边以null填充(0x00)
可变长度的字符串前面包括一个表示字符串长度的内容
有些可变长度的字符串以null结尾,有些不是.每个字符串中有符号表示属于哪种情况.
对于null结尾的字符串,最前面是字符串长度,这个长度不包括结尾的null字节,除非显式表明
如果存在可变长度的字符串在变乱结尾,并且变乱前面没有任何内容,这个字符串的长度=变乱长度-变乱中其他内容的长度.
有些变乱使用封包整数,这是一个特殊的格式,用来有效的描述无符号整数.封包整数可以存储一个8字节的整数,小整数(small integer)占用1、3或4字节.根据下面的表格,第一个字节的值决定了如何读这个数字:
第一个字节 | 格式 |
---|---|
0-250 | 第一个字节就是数字(0-250),不必要额外的字节. |
252 | 使用多于2字节,数字的范围是251-0xffff |
253 | 使用多于3字节,数字的范围是0xffff-0xfffff |
254 | 使用多于8字节,数字范围是0xfffff-0xffffffffffffffff |
二、事件头字段
每个变乱以LOG_EVENT_HEADER_LEN长度开头,这个常量在v1格式中时13,在v3及以上格式中是19.
v1:13字节:timestamp+type code+server ID+event length
v3:19字节:v1的字段+next position+flags
v4:19字节或更多:v3的字段+可能有其他信息
v1变乱头:
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+============================+
v1头的13个字节也包括在其他版本的事件头中.
v3变乱头
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+----------------------------+| next_position 13 : 4 |+----------------------------+| flags 17 : 2 |+============================+
和v1对比,v3以上中的事件头中包括两个额外的字段,总长度为19字节.
v4变乱头
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+----------------------------+| next_position 13 : 4 |+----------------------------+| flags 17 : 2 |+----------------------------+| extra_headers 19 : x-19 |+============================+
v4的事件头中包括一个extra_headers字段,是为了以后扩展用.当前x=19,所以v4和v3当前格式一样.
注意:extra_headers么有在FORMAT_DESCRIPTION_EVENT或ROTATE_EVENT的头中出现.
在log_event.h中,包括几个事件头的常量:
EVENT_TYPE_OFFSET = 4
SERVER_ID_OFFSET = 5
EVENT_LEN_OFFSET = 9
LOG_POS_OFFSET = 13
FLAGS_OFFSET = 17
事件头中包括以下信息:
timestamp
4字节.表示的是语句开始执行的时间,格式与TIMESTAMP SQL数据类型一样.
type_code
1字节.变乱类型.1表示START_EVENT_V3,2表示QEURY_EVENT,以此类推.这些数字定义在log_event.h的Log_event_type的枚举类中.
server id
4字节,产生这个变乱的mysqld服务器id.这个是在服务器中配置文件配置的,用于主从复制.server id会在循环复制时避免死循环(开启了--log-slave-updates配置).假设M1、M2和M3的server id分别是1、2、3,而且他们循环复制:M1是M2的主,M2是M3的主,M3是M1的主.他们的主从关系如下:
M1---->M2^ || |+--M3<-+
客户端发起了一个插入语句给M1,M1执行了之后,写入了M1的binlog文件中,包括了server id为1.这个事件被发给了M2,M2也执行了这个语句,然后写binlog的时候,server id还是1,因为这个事件最初是由M1发起的.然后M3也收到了这个事件,执行完成后写入到M3的binlog文件时,server id还是1.然后M1收到了这个事件之后,在执行插入语句之前,可以分析出server id=1,也就是这个语句最初是本机发起的,这个语句会被忽略执行.
event_length
4字节.事件的总长度,包括事件头和事件数据.大部分的事件小于1000字节,除非使用LOAD DATA INFILE(因为包括加载文件,所以他们可能很大)
next_position(v1不包括):4字节.下个时间在master的binlog中的位置.这个格式在binlog和relay log中不一样,而且与server版本有关(对于relay log来说,与master的版本有关)
v3版本的binlog:事件开头的偏移量,从binlog文件的开头开始计算.也便是说,在事件写入之前,等于tell()的值. 所以binlog的第一个事件的next_position=4,对于事件n和n+1,next_position(n+1)=next_position(n)+event_length(n).
v3版本的relay log,master是v1:可能是0,但是没法测试,因为现在已经基本没有3.23的服务器了.
v3版本的relay log,master是v3:开头变乱的偏移量和master中binlog文件一样,也是从master的binlog文件开头开始计算.
v4版本的binlog:事件结尾的偏移量,从binlog文件开头开始计算.也便是说,等于在事件被写入之后,正好等于tell()的值.所以binlog中第一个事件的next_position=4+event_length,对于事件n和n+1,next_position(n+1)=next_position(n)+event_length(n+1).
flags(v1中没有)
2字节,详见下一节.
extra_headers(v1和v3中不存在)
可变大小,当前为0.
变乱flag
对于v3及以上版本中,事件头中包括一个2字节的时间flag在FLAGS_OFFSET=17位置上.在log_event.h中并没有定义.
当前的变乱flag:
LOG_EVENT_BINLOG_IN_USE_F=0x1(5.0.3新增)
表示一个binlog文件是否正确的被关闭了.这个标志位只对FORMAT_DESCRIPTION_EVENT生效.当这个变乱被写入日志文件时,才会设置这个标志位.当日志文件后续被关闭后,这个标志位会被清除掉.(这是Mysql修改已经写完的binlog文件的唯一情况).
LOG_EVENT_THREAD_SPECIFIC_F=0x4(4.1.0新增)
仅供mysqlbinlog使用,使他能够正确的处理临时表.mysqlbinlog把binlog中的事件打印出来,让你能够理解打印出来的内容.但是如果两个独立的线程使用同样的临时表名,好比:
<thread id 1>CREATE TEMPORARY TABLE t (a INT);<thread id 2>CREATE TEMPORARY TABLE t (a INT);
这种情况下,简单的执行sql语句,会导致表t已经存在的错误.所以使用临时表的事件必要设置这个标志位,那样mysqlbinlog知道必要在变量值钱设置假的线程id,例如:
SET PSEUDO_THREAD_ID=1;CREATE TEMPORARY TABLE t (a INT);SET PSEUDO_THREAD_ID=2;CREATE TEMPORARY TABLE t (a INT);
这样,服务器接收到命令后就没有歧义了.所有情况下都打印SET PSEUDO_THREAD_ID,及时临时表没有用到,这样不会产生bug,但是会有点慢.
LOG_EVENT_SUPPRESS_USE_F=0x8(4.1.7新增)
在一个语句被记录前,抑制产生USE语句.用于任何不需要使用默认数据库的事件中,好比CREATE DATABASE和DROP DATABASE.
LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F=0x10(5.1.4新增)
在变乱写入日志文件中后,导致binlog内部的表映射版本增加.
过时的标志位:
LOG_EVENT_TIME_F(4.1.1过期).从未被设置过
LOG_EVENT_FORCED_ROTATE_F(4.1.1过期):这个标志位是在master的ROTATE_EVENT中配置的,但是没有任何用处.
三、变乱数据字段(变乱详细信息)
变乱数据部分的结构依赖于变乱类型:
v1和v3版本中,变乱类型完全决定了数据格式
v4中,数据部分的解析除了依赖于事件类型,还依赖于格式描述事件的信息.这是因为在v4中,允许包括一个extra headers字段,这个字段的大小是在格式描述事件中定义的.实际上,当前这个字段是空的.
数据部分包括固定大小和可变大小两部分.两部分都可以为空,这由事件类型决定.(比如,STOP_EVENT只包括头,数据内容都为空).
变乱数据的大小=变乱大小-变乱头大小.下面的规则对binlog中所有的变乱都通用:
对于所有相同类型的变乱,固定部分的大小一样.
对于所有相同类型的变乱,可变部分的大小可能不一样.
欢迎参与《Mysql Binlog事件结构》讨论,分享您的想法,维易PHP学院为您提供专业教程。
转载请注明本页网址:
http://www.vephp.com/jiaocheng/7885.html