MySQL通过Binlog进行主从数据的复制,Binlog是一种二进制格式的文件,理解Binlog二进制格式能够帮助我们进一步理解MySQL的主从复制原理。本文将对Binlog文件格式进行分析。
本文涉及的源码版本和相关参数如下:
- MySQL Server 5.7.19
- binlog_format:ROW
- binlog_row_image:FULL
一、Binlog文件Magic Number:
Binlog文件,前4个字节固定为一个Magic Number,十六进制值为fe62696e,如果一个文件其前4个字节不是这个Magic Number,那么就可以认为其不是一个有效的Binlog文件。
二、Binlog event:
Binlog文件除了最前面的4个字节之外,就是一个一个的event,event包含两个部分,event header和event data。通常event header大小固定,event data大小可变。
event整体结构如下:
+===================+
| event header |
+===================+
| event data |
+===================+
event header 和 event data 详细结构如下:
| ** event header ** |
| 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 |
| ** event data **|
| fixed part x : y |
| variable part |
event header 结构解析:
- timestamp:时间戳,表示该event的生成时间,占用4个字节
- type_code:event类型,占用1个字节
- server_id:生成event的server_id,占用4个字节
- event_length:event的大小,占用4个字节
- next_position:下一个event的位置,占用4个字节
- flags:event flags,占用2个字节
- extra_headers:额外的信息,占用的字节不确定,也可能没有。由event type为FORMAT_DESCRIPTION_EVENT 类型的event中的数据决定。
event data结构解析:
- fixed part:固定的部分,每一种类型的event,其fixed part部分占用的大小是固定的。具体大小由类型为 FORMAT_DESCRIPTION_EVENT 的event中的可变数组的值决定。
- variable part:可变的部分,这部分大小可变,具体由 event header 中的event_length 减去 event header 的大小 和 fixed part 部分的大小 获得。
三、FORMAT_DESCRIPTION_EVENT:
前面提到类型为FORMAT_DESCRIPTION_EVENT的event,这个event比较特殊,通常一个Binlog文件只有一个该类型的event,并且是Binlog文件中出现的第一个event。这个event存储着非常关键的元数据。
FORMAT_DESCRIPTION_EVENT类型的event,其event header固定为19个字节,没有extra_headers部分。其event data部分,只包含fixed part, 没有variable part部分。
fixed part部分如下:
- binlog 版本信息:占用2个字节
- mysql server 版本信息:占用50个字节
- timestamp 时间戳:占用4个字节
- header length:event header长度,占用1个字节,如果为19,表示所有类型的event,其event header的extra_headers部分都为空。
- 可变的数组,每个元素占用一个字节,数组大小与event类型数量相同,每个元素表示该类型的event data 固定部分(fixed part)占用的大小。
通过FORMAT_DESCRIPTION_EVENT event中的header length和可变的数组,就可以确定每个类型的event header大小和fixed part部分的大小。从而为解析每个类型的event打下了基础。
四、event 类型汇总:
分析源码文件 libbinlogevents/include/binlog_event.h 中的枚举类型 Log_event_type,获取所有的event类型如下,一共40个,并不是所有的类型都会使用,有一些只是兼容之前的版本。
- 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,
- TRANSACTION_CONTEXT_EVENT= 36,
- VIEW_CHANGE_EVENT= 37,
- XA_PREPARE_LOG_EVENT= 38,
- ENUM_END_EVENT
基本上每种类型的event,其格式各不相同,必须针对每一种类型的event进行解析,MySQL源码中也是不同的event都有其对应的c++类进行解析。