binlog基本认识
MySQL中的binlog是一个二进制文件,它记录了所有的增删改操作。节点之间的复制就是依靠binlog来完成的。binlog具有三种模式:
- Row模式
日志中会记录成每一行数据被修改的日志,然后在slave端再对相同的数据进行修改。例如:update xxx where id in(1,2,3,4,5);采用该模式则会记录5条记录。 - statement模式
每一条会修改数据的sql都会记录到 master的binlog中。slave在复制的时候sql Thread
会解析成和原来master端执行过的相同的sql来再次执行. - mixed模式
Mixed即混合模式,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。
新版本中的Statment level还是和以前一样,仅仅记录执行的语句。而新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更。
Binlog结构和内容
日志由一组二进制日志文件(Binlog),加上一个索引文件(index);Binlog是一个二进制文件集合,每个Binlog以一个4字节的魔数开头,接着是一组Events;
1.魔数:0xfe62696e对应的是0xfebin;
2.Event:每个Event包含header和data两个部分;header提供了Event的创建时间,哪个服务器等信息,data部分提供的是针对该Event的具体信息,如具体数据的修改;
3.第一个Event用于描述binlog文件的格式版本,这个格式就是event写入binlog文件的格式;
4.其余的Event按照第一个Event的格式版本写入;
5.最后一个Event用于说明下一个binlog文件;
6.Binlog的索引文件是一个文本文件,其中内容为当前的binlog文件列表,比如:
1 | D:\mysql\bin-log.000001 |
参考:https://dev.mysql.com/doc/internals/en/binary-log-structure-and-contents.html
Binlog的Event类型
官方提供的可能Event类型有36种,具体看下面的枚举:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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 = 23, UPDATE_ROWS_EVENT = 24, DELETE_ROWS_EVENT = 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 */ }; |
参考:https://dev.mysql.com/doc/internals/en/event-classes-and-types.html
Event结构官网提供了3个版本,分别是v1,v3,v4:
v1:用在MySQL 3.23
v3:用在MySQL 4.0.2-4.1
v4:用在MySQL 5.0之后
现在MySQL的版本基本都使用5.0之后的版本,可以直接看v4,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | +=====================================+ | 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 | +=====================================+ |
名字后面的两个数字表示:offset : length即从第几个字节开始,后面多少个字节用来存放数据
比如:timestamp(0 : 4)表示从第0个字节开始,往后四个字节用来存放timestamp
目前来说x=19,所有extra_headers是空的,y是fixed part的长度,不同的Event长度不一样。
参考:https://dev.mysql.com/doc/internals/en/event-structure.html
Event简要分析
1.从一个最简单的实例来分析其中的Event,包括创建表,插入数据,更新数据,删除数据;binlog_format使用的是默认的STATEMENT;
1 2 3 4 5 6 7 8 9 10 | CREATE TABLE `btest` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `age` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 insert into btest values(1,100,'zhaohui'); update btest set name='zhaohui_new' where id=1; delete from btest where id=1; |
2.查看所有的Events
1 | show binlog events; |
上图中一共出现了3中类型的Event,分别是Format_desc,Query和Xid,下面进行简单的分析
2.1Format_desc_Event
官网格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | +=====================================+ | event | timestamp 0 : 4 | | header +----------------------------+ | | type_code 4 : 1 | = FORMAT_DESCRIPTION_EVENT = 15 | +----------------------------+ | | server_id 5 : 4 | | +----------------------------+ | | event_length 9 : 4 | >= 91 | +----------------------------+ | | 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 | +=====================================+ |
使用十六进制方式打开文件bin-log.000001,以下是Format_desc_Event的十六进制代码:
可以先看前面的4+103=107个字节,4字节是binlog的魔数,103字节是Format_desc_Event,其中有19字节是header;
注:Binlog日志是小端字节顺序
0x5A0504AA四个字节是timestamp;0x0F一个字节表示type_code;0x00000001四个字节为server_id;0x00000067四个字节是event_length,对应的十进制就是103;
0x0000006b四个字节是next_position,即下一个Event的开始位置为107;ox0001两个字节是flags;header总计19字节。
data总字节数=103-19即84字节,排除掉前面的57个字节,剩余27字节表示post-header lengths for all event types;
post-header lengths:从START_EVENT_V3开始到第27个Event,每个Event的fixed part lengths;
Format_desc_Event位置是15,可以在图中找到15的位置是0x54,对应十进制是84,即fixed part lengths=84,而这个值刚好是57+27=84,所以Format_desc_Event不存在variable part;
参考:https://dev.mysql.com/doc/internals/en/binary-log-versions.html
2.2Query_Event
以下的create table产生的Query_Event的十六进制代码:
header共19字节,0x02一个字节表示type_code(Query_Event=2);0x00000101四个字节是event_length,对应的十进制就是257(pos=107,End_log_pos=364);
Query_Event在post-header的第二个位置0x0d,所有fix part lengths=13;
variable part=257-19-13=225字节
具体fix data和variable data:
1 2 3 4 5 6 7 8 9 10 11 | +==============================================================+ | fix | The ID of the thread 19 : 4 | | data +-----------------------------------------------------+ | | The time in seconds 23 : 4 | | +-----------------------------------------------------+ | | The length of the name of the database 27 : 1 | | +-----------------------------------------------------+ | | The error code 28 : 2 | | +-----------------------------------------------------+ | | The length of the status variable block 30 : 2 | +==============================================================+ |
在创建表产生一个Query_Event,insert、update以及delete执行之后分别产生了2个Query_Event和一个Xid_Event。
更多详细:https://dev.mysql.com/doc/internals/en/event-data-for-specific-event-types.html
2.3Xid_Event
以下的更新数据产生的Xid_Event的十六进制代码:
header共19字节,0x10一个字节表示type_code(XID_EVENT=16);0x0000001b四个字节是event_length,对应的十进制就是27(pos=536,End_log_pos=563);
2Xid_Event在post-header的第十六个位置0x00,所有fix part lengths=0;
variable part=27-19=8字节
8字节:The XID transaction number。
insert、update以及delete执行之后分别产生了Xid_Event,事务提交产生的事件。
更多详细:https://dev.mysql.com/doc/internals/en/event-data-for-specific-event-types.html
总结
本文主要对Mysql Binlog做了一个大体的介绍,包括:Binlog的参数,格式以及最重要的事件;事件数量比较多,从最简单的增删改查入手,介绍了几个比较常见的事件;
后续会继续学习其他事件,对Binlog有更加详细的了解。
作者:jerrik
链接:https://www.jianshu.com/p/e19d9312d1b5
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。