1 mysql binlog格式
binlog的格式经历了几个阶段:
- v1:mysql 3.23
- v3:mysql 4.0.2 到 4.1
- v4:mysql 5.0以上
v2版本只是短暂的存在过,本温主要介绍v4版本的binlog.
binlog格式如下:
- binlog文件以一个值为0Xfe62696e的魔数开头,这个魔数对应0xfe 'b''i''n'
- binlog由一系列的binlog event构成。每个binlog event包含header和data两部分:
- header部分提供的是event的公共的类型信息,包括event的创建时间,服务器等
- data部分提供的是针对该event的具体信息,如具体数据的修改
- 从mysql5.0版本开始,binlog采用的是v4版本,第一个event都是FORMAT_DESCRIPTION_EVENT用于描述binlog文件的格式版本,这个格式就是event写入binlog文件的格式
- 最后一个rotate event用于说明下一个binlog文件
event数据结构如下:
+=====================================+
| 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 |
+=====================================+
| footer | cksum |
+=====================================+
- timestamp:固定4字节展示是新纪元(epoch time)以来的秒数
- type_code:固定1字节event事件的编码,FORMAT_DESCRIPTION_EVENT编码0x0F, ROTATE_EVENT编码4. 具体事件码可参考binlog_event.h:Log_event_type
- server_id:固定4字节就是 show variables like '%server_id';出来的值
- event_length:固定4字节整个event的长度,包含固定和非固定长度
- next_position:固定4字节下一个event的开始位置.在 v4 版本中代表从 Binlog 一开始到下一个事件开始的偏移量, 比如到第一个事件的 next_position 就是 4,因为文件头有一个字节的长度。 然后接下去对于事件 n 和事件 n + 1 来说,他们有这样的关系:
next_position(n + 1) = next_position(n) + event_length(n) - flags:固定2字节 event flags
- extra_headers:看binlog文件是没有用到,实际使用中event header只有前19字节
- footer: 校验码 使用CRC32 长度是4字节 CHECKSUM_CRC32_SIGNATURE_LEN
2 常见event格式
2.1 XID_EVENT
当事务提交时,不论是statement还是row格式的binlog都会添加一个XID_EVENT作为事务的结束。该事件记录了该事务的ID。在mysql进行崩溃恢复时根据binlog中提交的情况来决定是否提交存储引擎中prepared状态的事务。
XID_EVENT前19个字节是通用头部,type是16(0x10)。data部分中Fixed data为空,而variable data为8个字节,格式如下:
+=====================================+
| 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 | xid 19:8 |
| data | |
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
样例
000002e0: ... 8e4e 675d 1062 0400 ...1.$.8.Ng].b..
000002f0: 001f 0000 0007 0300 0000 0009 0000 0000 ................
00000300: 0000 005e aaee 92
2.2 ROTATE_EVENT
当binlog文件大小达到max_binlog_size参数设置的值或执行flush logs命令时,binlog发生切换,这时会在当前使用的binlog文件末尾添加一个ROTATE_EVENT事件,将下一个binlog文件的名称和位置记录到该事件中。
格式如下:
+=====================================+
| 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 | pos 19 : 8 |
| data +----------------------------+
| | variable part |
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
样例
00000300: ... 67 9467 5d04 6204 0000 ...^...g.g].b...
00000310: 2f00 0000 3603 0000 0000 0400 0000 0000 /...6...........
00000320: 0000 6d79 7371 6c2d 6269 6e2e 3030 3030 ..mysql-bin.0000
00000330: 3234 68ee 6e73 24h.ns
前19个字节是通用头部,type是0x04。data部分中flag为0x0000,接着是event data部分,首先的8个字节为Fixed data部分,记录的是下一个binlog的位置偏移4,而余下来的47-19-8-4=16个字节为Variable data部分,记录的是下一个binlog的文件名mysql-bin.000024,
2.3 FORMAT_DESC_EVENT
binlog第一个event也就是format_desc event开始分析(mysql日志是小端字节序)
- 从库的内存中会存放主库的信息,变量是Master_info.mi_description_event,queue_event函数中,case binary_log::FORMAT_DESCRIPTION_EVENT分支报存相关信息
- 将从库relay log的FD Event记录和主库相同,即更新Relay_log_info.rli_description_event
格式:
+=====================================+
| event | timestamp 0 : 4 |
| header +----------------------------+
| | type_code 4 : 1 | = FORMAT_DESCRIPTION_EVENT = 15
| +----------------------------+
| | server_id 5 : 4 |
| +----------------------------+
| | event_length 9 : 4 |
| +----------------------------+
| | next_position 13 : 4 |
| +----------------------------+
| | flags 17 : 2 |
+=====================================+
| event | binlog_version 19 : 2 | = 4
| data +----------------------------+
| | server_version 21 : 50 |
| +----------------------------+
| | create_timestamp 71 : 4 |
| +----------------------------+
| | header_length 75 : 1 |
| +----------------------------+
| | post-header 76 : n | = array of n bytes, one byte per event
| | lengths for all | type that the server knows about
| | event types |
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
样例:
00000000: fe62 696e 2946 675d 0f62 0400 0078 0000 .bin)Fg].b...x..
00000010: 007c 0000 0000 0004 0038 2e30 2e31 352d .|.......8.0.15-
00000020: 6465 6275 6700 0000 0000 0000 0000 0000 debug...........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0029 4667 5d13 ...........)Fg].
00000050: 000d 0008 0000 0000 0400 0400 0000 6000 ..............`.
00000060: 041a 0800 0000 0808 0802 0000 000a 0a0a ................
00000070: 2a2a 0012 3400 0a01 3111 8ca8 29
2.4 PREVIOUS_GTIDS_LOG_EVENT
开启GTID情况下,是binlog文件的第二个event,包含之前所有binlog的gtid的集合(包括删除的),用于加快扫描速度。relaylog中也有这类的event,用于记录从库IO线程接收到的GTID,sql线程跳过该event,不会应用。
+=====================================+
| event | timestamp 0 : 4 |
| header +----------------------------+
| | type_code 4 : 1 | = PREVIOUS_GTIDS_LOG_EVENT = 35
| +----------------------------+
| | server_id 5 : 4 |
| +----------------------------+
| | event_length 9 : 4 |
| +----------------------------+
| | next_position 13 : 4 |
| +----------------------------+
| | flags 17 : 2 |
+=====================================+
| event | bnumber of sides 19 : 8 |
| data +----------------------------+
| | server_uuid 27 : 16 |
| +----------------------------+
| | n_intervals 43 : 8 |
| +----------------------------+
| | inter_start 51 : 8 |
| +----------------------------+
| | inter_next 59 : 8 |
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
样例:
00000070: fab 015e **..4..........^
00000080: 236a 0400 0047 0000 00c3 0000 0080 0001 #j...G..........
00000090: 0000 0000 0000 006c ea54 addd e611 e995 .......l.T......
000000a0: 0552 5400 d070 2c01 0000 0000 0000 001a .RT..p,.........
000000b0: 0200 0000 0000 001f 0200 0000 0000 00b7 ................
000000c0: 102d 950a
2.5 QUERY_EVENT
QUERY_EVENT类型的事件通常在一下几个情况中使用:
- 事务开始时,在binlog中有一个QUERY_EVENT类型的BEGIN。
- 在statement格式中,具体执行的SQL语句会保存在该事件中。
- 对于ROW格式的binlog,所有DDL操作以文本的形式记录在该事件中。
事件格式:
+=====================================+
| event | timestamp 0 : 4 |
| header +----------------------------+
| | type_code 4 : 1 | = QUERY_EVENT = 2
| +----------------------------+
| | server_id 5 : 4 |
| +----------------------------+
| | event_length 9 : 4 |
| +----------------------------+
| | next_position 13 : 4 |
| +----------------------------+
| | flags 17 : 2 |
+=====================================+
| event | slave_proxy_id 19 : 4 | 执行该语句的线程ID
| data +----------------------------+
| | execution time 23 : 4 | 语句执行时间 单位s
| +----------------------------+
| | schema length 27 : 1 | schema字符串长度
| +----------------------------+
| | error code 28 : 2 | 错误码
| +----------------------------+
| | status-var |
| | length13 : 30 : 2 | status-var的长度
| +----------------------------+
| | status-var 32 : x | 此处开始是变长部分
| +----------------------------+
| | schema 32+x : y | 当前选择的databases
| +----------------------------+
| | 00 35+x+y : 1 | 默认
| +----------------------------+
| | query 36+x+y : z | query字符串
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
样例:
00000110: ... 3846 675d 0262 0400 004b 0000 005d ..8Fg].b...K...]
00000120: 0100 0008 000b 0000 0000 0000 0004 0000 ................
00000130: 1d00 0000 0000 0001 2000 a045 0000 0000 ........ ..E....
00000140: 0603 7374 6404 2100 2100 2100 12ff 0064 ..std.!.!.!....d
00000150: 6561 6e00 4245 4749 4e9d 1cb9 eb38 46
2.6 WRITE_ROWS_EVENT
事件格式:
+=====================================+
| event | timestamp 0 : 4 |
| header +----------------------------+
| | type_code 4 : 1 | = WRITE_ROWS_EVENT = 30
| +----------------------------+
| | server_id 5 : 4 |
| +----------------------------+
| | event_length 9 : 4 |
| +----------------------------+
| | next_position 13 : 4 |
| +----------------------------+
| | flags 17 : 2 |
+=====================================+
| event | table_id 19 : 6 | table id
| data +----------------------------+
| | flag 25 : 2 |
| +----------------------------+
| | column num 27 : 1 | 列数目
| +----------------------------+
| | bitmap 28 : 1 |columns-present-bitmap : ff。包含所有列则为0xff
| +----------------------------+
| | null bitmap: 29 : 1 | |
| +----------------------------+
| | column values 30 : x | 此处开始是变长部分,具体的列值
+=====================================+
| footer | cksum 4个字节 |
+=====================================+
举例
CREATE TABLE `hash1` (
`id1` varchar(11) NOT NULL,
`id2` int(11) NOT NULL,
`id3` varchar(20) NOT NULL,
PRIMARY KEY (`id1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into hash1 values(1,1,1);
00000170: c4 6d84 5d1e 6204 0000 2c00 0000 9d01 ..m.].b...,.....
00000180: 0000 0000 3e00 0000 0000 0100 0200 03ff ....>...........
00000190: 0001 3101 0000 0001 3103 2065 c7 ..1.....1. e..m.
其中
timestamp: c4 6d84 5d
...
table id:3e00 0000 00
flag: 0010 2个字节可以包含以下信息。该事件是否是语句的最后一个事件,
是否需要进行外键约束检查,针对innodb的二级索引是否需要进行唯一性检查,
该事件是否包含了完整一行数据也就是说覆盖了所有列。
Var-size header len: 0002
column num: 03 列数目
columns-present-bitmap : ff。包含所有列则为0xff
null bitmaps: 00
id1的值: 0131 id1是varchar类型,01表示字符串长度,31是值
id2的值: 01000000 int类型4字节
2.7 HEARTBEAT_EVENT
heartbeat event 是不写到binlog中的。若使用heartbeat event 记录一致性位点信息事件格式:
+=====================================+
| event | timestamp 0 : 4 |
| header +----------------------------+
| | type_code 4 : 1 | = WRITE_ROWS_EVENT = 30
| +----------------------------+
| | server_id 5 : 4 |
| +----------------------------+
| | event_length 9 : 4 |
| +----------------------------+
| | next_position 13 : 4 |
| +----------------------------+
| | flags 17 : 2 |
+=====================================+
| event | binlog |
| | file name 19 : X | 此处开始是变长部分,当前binlog
| data | |
+=====================================+
| footer | cksum 4个字节 |
+=====================================+