深入理解MySQL主从原理
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2 重点Event之 FORMAT_DESCRIPTION_EVENT和PREVIOUS_GTIDS_LOG_EVENT

2.2.1 FORMAT_DESCRIPTION_EVENT

1.FORMAT_DESCRIPTION_EVENT的作用

FORMAT_DESCRIPTION_EVENT是binary log的第一个Event。这个Event比较简单,因为它携带的数据都是固定的,没有可变部分。其中包含binary log的版本信息、MySQL的版本信息、Event_header的长度,以及每个Event type的固定部分的长度。

下列信息将会保存在从库的内存中:

(1)在从库的内存中保存主库的信息,源码变量是Master_info.mi_description_event。

(2)将从库的relay log的FORMAT_DESCRIPTION_EVENT Event记录为和主库相同的值,它存储在源码变量Relay_log_info.rli_description_event中。Format_description_log_event::do _apply_event函数中,包含如下片段:

至少在以下场景下会读取其中的信息:

(1)每次SQL线程应用Event的时候都会获取其Event_header的长度和相应Event固定部分的长度。

(2)在I/O线程启动的时候检测版本,参考get_master_version_and_clock函数。

(3)将信息写入relay log开头的FORMAT_DESCRIPTION_EVENT。

它一定出现在binary log开头,位置固定为#4。

2.源码重要接口

主库

· 初始化构造函数:Format_description_log_event::Format_description_log_event(uint8_t binlog_ver,const char* server_ver=0);

· 写入binlog cache:Format_description_log_event::write(IO_CACHE* file)。

从库

· 读取构造函数:Format_description_log_event::Format_description_log_event(const char* buf,uint event_len,const Format_description_event *description_event);

· 应用函数:Format_description_log_event::do_apply_event。

3.主体格式

FORMAT_DESCRIPTION_EVENT没有可变部分,如图2-2所示。

图2-2

其中,固定部分如下。

binlog_version:2字节,binary log的版本为4。

server_version:50字节,MySQL的版本为字符串形式。

create_timestamp:4 字节,在 MySQL 每次启动时,第一个 binary log 的 FORMAT_DESCRIPTION_EVENT都会记录其启动时间,在其他情况下为0。源码中有如下解释,供参考。

header_length:1字节,Event header的长度当前为19。

array of post-header:当前MySQL版本为39字节。这是一个数组,用于说明每个Event类型的固定部分有多大。

4.实例解析

下面是一个FORMAT_DESCRIPTION_EVENT(mysqlbinlog--hexdump 输出):

从第五行开始解析如下。

04 00:binary log的版本为4。

35 2e~00 00:当前MySQL的版本是5.7.22-22-debug-log。

98 94 ad 5c:小端显示,因为本binary log是MySQL启动以来的第一个binary log,所以这里就是相应的启动时间,十六进制值为5cad9498,十进制值为1554879640。转换一下,时间如下:

13:Event header的长度,十进制值为19。

38 0d~00 01:不做解析,表示的是每个Event固定部分的大小。

5.生成时机

FORMAT_DESCRIPTION_EVENT作为binary log的第一个Event,一般都是在binary log切换的时候发生的。例如,flush binary logs命令;binary log自动切换;重启MySQL实例。

注意,在本Event的Event header中,flags如果为 LOG_EVENT_BINLOG_IN_USE_F,则说明当前binary log没有关闭(比如本binary log为当前写入文件或者异常关闭MySQL实例)。如果异常关闭MySQL实例,那么会检测这个值以决定是否做binary log recovery。