MySQL Binlog event介绍 - saviochen/mysql_docs GitHub Wiki
1 综述
binlog文件头部固定以4个字节开头,这四个字节称为BINLOG_MAGIC(fe 62 69 6e)。binlog是由event组成,event是binlog的最小组成单元,每个binlog文件以一个Format_desc类型的event开始,以一个Rotate类型的event结束(但也有特殊情况,当数据库出现宕机的情况,重新启动数据库会生成一个新的binlog文件,但是宕机之前的最新binlog文件中,不是以ROTATE_EVENT结束的)。在FORMAT_DESCRIPTION_EVENT和ROTATE_EVENT之间是各种不同event,每个event代表Master上不同的操作。
binlog的内容可以使用mysqlbinlog工具解析,也可以使用SHOW MASTER LOGS查看。
2 binlog event类型
binlog所有类型定义在binlog_event.h文件中的Log_event_type中,下面是MySQL-8.0.30的所有binlog event类型:
enum Log_event_type {
UNKNOWN_EVENT = 0,
START_EVENT_V3 = 1,
QUERY_EVENT = 2,
STOP_EVENT = 3,
ROTATE_EVENT = 4,
INTVAR_EVENT = 5,
SLAVE_EVENT = 7,
APPEND_BLOCK_EVENT = 9,
DELETE_FILE_EVENT = 11,
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,
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,
PARTIAL_UPDATE_ROWS_EVENT = 39,
TRANSACTION_PAYLOAD_EVENT = 40,
HEARTBEAT_LOG_EVENT_V2 = 41,
ENUM_END_EVENT /* end marker */
};
下面介绍几种常见的binlog event类型:
FORMAT_DESCRIPTION_EVENT:每个binlog文件开头的一个描述信息的event。ROTATE_EVENT:当MySQL切换至新的binlog文件的时候,MySQL会在旧的binlog文件中写入一个ROTATE_EVENT,表示新的binlog文件的文件名,以及第一个偏移地址。当在数据库中执行FLUSH LOGS语句或者binlog文件的大小超过max_binlog_size就会切换新的binlog文件。TABLE_MAP_EVENT:TABLE_MAP_EVENT只有在binlog文件是以ROW格式记录的时候,才会使用。binlog中记录的每个更改的记录之前都会有一个对应要操作的表的TABLE_MAP_EVENT。TABLE_MAP_EVENT中记录了表的定义(包括database name,table name,column_count,column_type,metadata(varchar最长长度),null_bits等,校验码等),并且会将这个表的定义对应于一个数字,称为table_id。设计TABLE_MAP_EVENT类型event的目的是为了当主库和从库之间有不同的表定义的时候,复制仍能进行。如果一个事务中操作了多个表,多行记录,在binlog中会将对多行记录的操作event进行分组,每组行记录操作event前面会出现对应表的TABLE_MAP_EVENT。QUERY_EVENT:记录更新操作的语句。WRITE_ROWS_EVENT:在以ROW格式记录的binlog文件中,WRITE_ROWS_EVENT记录了插入的行记录。UPDATE_ROWS_EVENT:在以ROW格式记录的binlog文件中,UPDATE_ROWS_EVENT记录了更新的行记录。DELETE_ROWS_EVENT:在以ROW格式记录的binlog文件中,DELETE_ROWS_EVENT记录了删除的行记录。QUERY_LOG_EVENT:记录更新操作的语句。包括database名、执行时间、错误码、校验码等。ROWS_QUERY_LOG_EVENT:在row格式复制模式下,将query以语句形式记录。在5.6.2版本之后,可以通过设置binlog_rows_query_log_events参数来控制在row格式复制模式下是否需要将query语句记录到binlog文件中。XID_EVENT:表示支持内部XA的存储引擎上的事务提交。正常的事务是通过QUERY_EVENT来发送一个BEGIN语句并且通过QUERY_EVENT来发送一个COMMIT语句(如果事务回滚则发送的是ROLLBACK)实现。GITD_LOG_EVENT:开启GTID模式的场景下,每次事务commit提交时,MySQL会在binlog中事务开始写入一个GITD_LOG_EVENT,记录该事务的GTID事务号(sid、gno)。PREVIOUS_GTID_LOG_EVENT:在开启GTID的模式下,每个binlog文件开始会记录一个PREVIOUS_GTID_LOG_EVENT,PREVIOUS_GTID_LOG_EVENT中会包含当前binlog之前所有binlog中的GTID集合。ANONYMOUS_GTID_LOG_EVENT:MySQL在binlog中记录每一个匿名事务之前会记录一个ANONYMOUS_GTID_LOG_EVENT表示接下来的事务是一个匿名事务。
3 binlog event格式
从MySQL5.0版本开始,binlog采用的是v4版本,v4版本的event主要由event header部分和post-header以及variable part部分组成。
- event header是每个event都会有的部分,并且每个event header的格式是相同的,固定为19个字节长度,event的长度,event的类型,下一个event的偏移位置等信息,都可以在event header中获取到,具体如下:
| 字段 | 字节数 | 描述 |
|---|---|---|
| timestamp | 4 | 记录的是该事务记录的时间 |
| type_code | 1 | 记录的是该event的类型,具体的event类型,见上面的Log_event_type |
| server_id | 4 | 记录的是执行该event的server的server_id号 |
| event_length | 4 | 该event的长度,共占多少字节 |
| next_position | 4 | 下一个event在binlog文件中的偏移位置 |
| flag | 2 | 标记 |
- extra_headers指定了除公共头部外的内容,但是目前版本的binlog格式中,这一部分不存在的。
- fixed_part部分在某些文章中也被称做post-header,每个类型的event之间的post-header部分是不相同的,但是同一类型的event占用的post-header字节数是一样的。
- variable part是event真实记录具体信息的部分,有些时候也被称作payload或者body。