MySQL Binlog 文件格式解析(HEARTBEAT_LOG_EVENT)

MySQL 通过 Binlog 进行主从数据的复制,Binlog 由多种不同类型的 event 组成,本文简单介绍 event 类型为 HEARTBEAT_LOG_EVENT 的结构。

本文涉及的源码版本 MySQL Server 5.7.19

1. HEARTBEAT_LOG_EVENT 有什么用?

MySQL 主从复制通过 Binlog 来同步数据,正常情况下主库写入数据,以 Binlog event 结构发送给从库,从库应用 Binlog。这一过程中,主库 binlog dump 线程在发送数据,从库 io 线程在接收数据,dump 线程与 io 线程之间建立网络通信,如果主库长时间没有数据写入,主从库之间的网络连接需要定时发送心跳包,来让从库知道主库还活着,HEARTBEAT_LOG_EVENT 就是主库发送的心跳事件。

HEARTBEAT_LOG_EVENT 属于控制类的 event,它与通常的 WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT 等不同,HEARTBEAT_LOG_EVENT 不需要写入到文件中,因为它只是用于确认主库是否还活着,并没有实质性的数据需要存储,收到之后,就可以丢弃,而其他类型的 event 必须写入到文件中,以便在级联复制中,能够将数据同步到下一个节点。

2. HEARTBEAT_LOG_EVENT 格式

在源码文件 sql/rpl_binlog_sender.cc 中,通过类 Binlog_sender 来向从库发送 HEARTBEAT_LOG_EVENT,函数名如下:

int Binlog_sender::send_heartbeat_event(my_off_t log_pos)

从该函数中,可以找到 HEARTBEAT_LOG_EVENT 的具体格式,如下:

event header(19字节)
event data
event checksum(4字节)
  • event header 格式是固定的,大小为 19 字节,参见:MySQL Binlog文件格式解析,其中 event type 值为 HEARTBEAT_LOG_EVENT,也就是 27。
  • event data 存储的是 binlog 文件名称,比如 mysql-bin.000002,长度与具体名称相关。
  • event checksum,4 字节,checksum 校验码,每个 event 都会有。

以上格式可以通过 tcpdump 抓包来验证,在主从节点没有写入的条件下,抓包一段时间,然后使用 Wireshark 分析抓到的包。

抓包命令:
tcpdump -i eth0 tcp port 3306 -w data.cap

在抓包分析时,发现 HEARTBEAT_LOG_EVENT event 数据之前,还有 1 个字节的额外数据,值为 0。另外如果打开半同步插件,则会有 3 个字节的额外数据,其中 2 个字节由半同步插件添加,见源码函数:

inline int Binlog_sender::reset_transmit_packet(ushort flags, size_t event_len)
{
m_packet.length(0);  // size of the content

// 额外添加的 1 个字节
m_packet.qs_append('\0'); // Set this as an OK packet

// 半同步插件会再添加额外 2 个字节
if (m_observe_transmission &&
      RUN_HOOK(binlog_transmit, reserve_header, (m_thd, flags, &m_packet)))
  {
    set_unknow_error("Failed to run hook 'reserve_header'");
    DBUG_RETURN(1);
  }
}

文章评论

0条评论