目录
1. 它是什么?
Previous_gtids_log_event 是一个二进制日志事件,它位于每个 binlog 文件的开头 (在 FORMAT_DESCRIPTION_EVENT 之后)。
它的作用是 记录在当前的 binlog 文件之前,所有已经执行过的 GTID 集合。
可以把它理解为 "本文件之前所有 binlog 的 GTID 目录" 或 "GTID 上下文"。
2. 它的作用和重要性
在 MySQL 启用了 GTID(全局事务标识符) 复制后,Previous_gtids_log_event 变得至关重要。它的主要作用有:
- 确定复制起点 :当一个新的从库连接到主库,或者一个已经存在的从库需要重新获取日志时,它会告诉主库"我已经执行过的 GTID 集合是 X"。主库通过对比自己的
Previous_gtids_log_event和Gtid_log_event,就能精确地知道应该从哪个 binlog 文件、哪个位置开始发送数据,确保不会重复发送已经执行过的事务,也不会漏掉任何事务。 - 保证数据一致性 :它构成了 GTID 的连续性。通过检查所有 binlog 文件的
Previous_gtids_log_event和文件内部的Gtid_log_event,可以验证整个复制链的 GTID 集合是否完整、无空洞。 - Purge 操作的依据 :MySQL 在自动清理(purge)旧的 binlog 文件时,会确保不会删除任何还包含有从库未执行事务的 binlog 文件。
Previous_gtids_log_event是判断这些依赖关系的关键信息。
3. 它是如何计算的?
Previous_gtids_log_event 的内容是一个 GTID 集合,其计算逻辑非常直观:
它等于上一个 binlog 文件中的 Previous_gtids_log_event 的内容,加上上一个 binlog 文件自身记录的所有 Gtid_log_event。
我们可以用一个公式和例子来理解:
计算公式:
当前文件_N 的 Previous_gtids_log_event = 文件_(N-1) 的 Previous_gtids_log_event + 文件_(N-1) 中所有的 GTID
详细示例:
假设我们有三个 binlog 文件:binlog.000001, binlog.000002, binlog.000003。
-
binlog.000001
Previous_gtids_log_event:空集合 {}- 解释:因为它是第一个文件,在它之前没有任何 GTID 事务。
- 文件内容:
Gtid_log_event: server_uuid:1-1(事务1)Gtid_log_event: server_uuid:1-2(事务2)
- 文件结束时,其包含的完整 GTID 集合为:
{server_uuid:1-1, server_uuid:1-2}
-
binlog.000002
Previous_gtids_log_event:{server_uuid:1-1, server_uuid:1-2}- 解释:这个集合就是上一个文件(binlog.000001)的
Previous_gtids_log_event(空)加上它自己包含的所有 GTID(1-1, 1-2)。
- 解释:这个集合就是上一个文件(binlog.000001)的
- 文件内容:
Gtid_log_event: server_uuid:1-3(事务3)Gtid_log_event: server_uuid:1-4(事务4)
- 文件结束时,其包含的完整 GTID 集合为:
{server_uuid:1-1, server_uuid:1-2, server_uuid:1-3, server_uuid:1-4}
-
binlog.000003
Previous_gtids_log_event:{server_uuid:1-1, server_uuid:1-2, server_uuid:1-3, server_uuid:1-4}- 解释:这个集合就是上一个文件(binlog.000002)的
Previous_gtids_log_event(1-1, 1-2)加上它自己包含的所有 GTID(1-3, 1-4)。
- 解释:这个集合就是上一个文件(binlog.000002)的
- 文件内容:
Gtid_log_event: server_uuid:1-5(事务5)
-
执行purge binlog to binlog.000003
- binlog.0000001, binlog.000002被删除
-
binlog.000004
- 创建新binlog文件
Previous_gtids_log_event:{server_uuid:1-1, server_uuid:1-2, server_uuid:1-3, server_uuid:1-4}- 解释:这个集合就是上一个文件(binlog.000003)的
Previous_gtids_log_event(1-1, 1-2, 1-3, 1-4)加上它自己包含的所有 GTID(1-5)。
- 解释:这个集合就是上一个文件(binlog.000003)的
- 文件内容:(新的 GTID 事务会记录在这里)
4. 如何查看它?
你可以使用 MySQL 官方提供的 mysqlbinlog 工具来查看这个事件。
bash
mysqlbinlog binlog.000002 | head -20
在输出的开头部分,你会看到类似这样的内容:
# at 4
#240101 10:00:00 server id 1 end_log_pos 123 CRC32 0xabcdefgh
# Position Timestamp Type Master ID Size Master Pos Flags
# 4 9a 8c 7b 5e 0f 01 00 00 00 77 00 00 00 7b 00 00 00 00 00
# a4 55 0f a8
# Previous-GTIDs
# server_uuid:1-4
更清晰的方式是使用 --verbose 选项:
bash
mysqlbinlog --verbose binlog.000002 | grep -A 10 "Previous-GTIDs"
输出会直接显示 GTID 集合:
# Previous-GTIDs
# server_uuid:1-4
在 MySQL 8.0 及以上版本,你还可以查询 performance_schema 中的 binary_log_transaction_compression_stats 视图(虽然不是直接查询,但可以获取相关信息),或者直接使用 SHOW BINLOG EVENTS 命令,但 mysqlbinlog 是最标准、最清晰的方式。
特殊情况
- 服务器首次启动 :第一个 binlog 文件的
Previous_gtids_log_event是空的。 - 服务器重启 :服务器重启后,会创建一个新的 binlog 文件。这个新文件的
Previous_gtids_log_event会严格按照上述规则计算,即等于上一个文件的所有 GTID 集合。 - 手动执行
RESET MASTER:这个命令会清空所有 GTID 执行历史,删除所有 binlog 文件,并从一个全新的、Previous_gtids_log_event为空的 binlog 文件开始。请在生产环境,尤其是复制环境中极其谨慎地使用此命令。
总结
| 特性 | 描述 |
|---|---|
| 是什么 | 一个记录"本文件之前所有 GTID"的事件。 |
| 位置 | 每个 binlog 文件的开头。 |
| 作用 | 确定复制起点、保证 GTID 连续性、辅助 binlog 清理。 |
| 计算规则 | 当前文件_Previous = 上一个文件_Previous + 上一个文件_所有GTID |
| 查看方式 | mysqlbinlog <binlog-file> |
理解 Previous_gtids_log_event 对于深入掌握 MySQL GTID 复制的工作原理和故障排查非常有帮助。
补充说明:
Q: 新建binlog 文件时,Previous_gtids_log_event可以认为是所有已经执行过的gtid集合 executed gtid set吗?
A: NO. 因为如果事务执行时设置不记录binlog,事务gtid 虽然在executed gtid set中,但不会在binlog文件。所以两者不是等价的。