GTID 集合详解
核心定义 GTID(Global Transaction Identifier)是 MySQL 为每个已提交事务生成的全局唯一编号。GTID 集合用于描述一组事务编号范围,是判断主从复制位置、复制延迟、日志缺失和数据一致性的关键依据。
1. GTID 的基本格式
GTID 的标准格式是:
source_id:transaction_id
示例:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1
含义:
| 部分 | 说明 |
|---|---|
source_id | 事务来源实例的 UUID,通常对应 server_uuid |
transaction_id | 该实例上递增的事务序号 |
多个连续事务可以合并为范围:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-100
多个来源实例或多个范围可以组合成 GTID 集合:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-100,
9E11FA47-71CA-11E1-9E33-C80AA9429562:1-50:80-120
2. GTID 集合解决的问题
传统复制依赖 binlog 文件名和 position,例如:
mysql-bin.000123:456789
这种方式在主从切换、故障恢复、重新指向主库时容易出错。GTID 的核心价值是把复制位置从“物理日志位置”提升为“全局事务集合”。
| 对比项 | binlog file + position | GTID |
|---|---|---|
| 定位方式 | 依赖具体 binlog 文件和偏移量 | 依赖全局事务编号 |
| 主从切换 | 需要人工找位点 | 可根据已执行集合自动定位 |
| 故障恢复 | 容易找错 position | 更容易判断缺失事务 |
| 可读性 | 偏底层物理位置 | 可表达事务范围 |
GTID 让 MySQL 能够判断:从库已经执行了哪些事务,还缺哪些事务,应从新主库拉取哪些事务。
3. GTID 集合的表示方法
3.1. 单个事务
server_uuid:1
表示某个 server_uuid 上的第 1 个事务。
3.2. 连续事务范围
server_uuid:1-100
表示从 1 到 100 的连续事务。
3.3. 非连续事务范围
server_uuid:1-50:80-120
表示 1 到 50、80 到 120 已存在,中间 51 到 79 缺失或未包含。
3.4. 多个 server_uuid
uuid_a:1-100,
uuid_b:1-20
表示集合中同时包含来自多个 MySQL 实例的事务。多源复制、主从切换、级联复制等场景中可能看到多个 UUID。
4. 主库上的核心 GTID 变量
4.1. gtid_executed
gtid_executed 表示当前实例已经执行过的全部 GTID 集合。
查看方式:
SHOW VARIABLES LIKE 'gtid_executed';
或:
SELECT @@GLOBAL.gtid_executed;
在主库上,它可以理解为“主库已经产生并执行过的事务集合”。在从库上,它表示“从库本地已经执行过的事务集合”,其中既可能包含复制来的事务,也可能包含从库本地执行的事务。
4.2. gtid_purged
gtid_purged 表示当前实例已经执行过,但对应 binlog 已经被清理掉的 GTID 集合。
查看方式:
SHOW VARIABLES LIKE 'gtid_purged';
它常用于判断从库是否还能从主库补齐缺失事务。
gtid_purged 风险 如果从库缺失的 GTID 已经落入主库
gtid_purged,说明主库对应 binlog 已被清理,从库无法再通过正常复制补齐这部分事务,通常需要重新备份恢复或从其他保留日志的实例补齐。
4.3. gtid_executed 与 gtid_purged 的关系
可以简化理解为:
gtid_executed:当前实例执行过的全部事务
gtid_purged:执行过但 binlog 已清理的事务
因此:
gtid_purged 通常是 gtid_executed 的子集
保留在 binlog 中、仍可用于复制补齐的事务,大致可以理解为:
gtid_executed - gtid_purged
5. 从库上的复制状态 GTID 集合
从库状态中最关键的是 Retrieved_Gtid_Set 和 Executed_Gtid_Set。
查看方式:
SHOW REPLICA STATUS\G
在旧版本 MySQL 中也可能使用:
SHOW SLAVE STATUS\G
5.1. Retrieved_Gtid_Set
Retrieved_Gtid_Set 表示复制 IO 线程已经从主库拉取到本地 relay log 的 GTID 集合。
含义:
主库 binlog
↓ IO 线程拉取
从库 relay log
↓
Retrieved_Gtid_Set
它代表“已经下载到从库”的事务,但不代表已经执行完成。
5.2. Executed_Gtid_Set
Executed_Gtid_Set 表示从库 SQL 线程已经执行完成的 GTID 集合。
含义:
从库 relay log
↓ SQL 线程重放
从库数据文件
↓
Executed_Gtid_Set
它代表“已经在从库执行完成”的事务。
5.3. 两者的关系
正常情况下:
Executed_Gtid_Set ⊆ Retrieved_Gtid_Set
如果 Retrieved_Gtid_Set 持续增长,说明 IO 线程仍在拉取日志。
如果 Executed_Gtid_Set 持续追赶 Retrieved_Gtid_Set,说明 SQL 线程仍在执行 relay log。
如果两者长期差距扩大,通常表示 SQL 线程执行慢、复制延迟扩大或 SQL 线程报错停止。
6. 主从复制中的 GTID 流程
GTID 复制链路可以抽象为:
主库提交事务
↓
生成 GTID 并写入 binlog
↓
从库 IO 线程拉取 binlog
↓
写入 relay log,Retrieved_Gtid_Set 增长
↓
从库 SQL 线程重放 relay log
↓
写入从库数据,Executed_Gtid_Set 增长
对应关系:
| 阶段 | 关键对象 | 代表含义 |
|---|---|---|
| 主库提交 | gtid_executed | 主库已执行的事务 |
| 主库清理 binlog | gtid_purged | 主库已清理日志的事务 |
| 从库拉取 | Retrieved_Gtid_Set | 从库已下载到 relay log 的事务 |
| 从库执行 | Executed_Gtid_Set | 从库已重放完成的事务 |
7. 如何判断主从同步是否正常
7.1. IO 线程是否正常
关注字段:
Replica_IO_Running: Yes
Retrieved_Gtid_Set: 持续增长或接近主库 gtid_executed
如果主库仍有写入,但 Retrieved_Gtid_Set 不增长,可能是 IO 线程异常、网络异常、账号权限异常或主库 binlog 缺失。
7.2. SQL 线程是否正常
关注字段:
Replica_SQL_Running: Yes
Executed_Gtid_Set: 持续追赶 Retrieved_Gtid_Set
如果 Retrieved_Gtid_Set 增长但 Executed_Gtid_Set 不增长,通常是 SQL 线程执行失败、遇到重复键、表结构不一致、锁等待或从库性能不足。
7.3. 是否存在复制延迟
复制延迟可以从两个角度观察:
| 角度 | 判断方法 |
|---|---|
| 时间延迟 | 查看 Seconds_Behind_Source 或 Seconds_Behind_Master |
| 事务集合差距 | 比较 Retrieved_Gtid_Set 与 Executed_Gtid_Set 的差距 |
时间延迟可能受采样和线程状态影响,GTID 集合差距更适合判断“还有哪些事务未执行”。
8. 常见 GTID 集合判断场景
8.1. 从库缺事务
现象:从库 Executed_Gtid_Set 小于主库 gtid_executed。
主库 gtid_executed: uuid:1-100
从库 Executed_Gtid_Set: uuid:1-80
含义:从库还缺少 uuid:81-100。
如果这些事务仍在主库 binlog 中,从库可以继续复制追上;如果已落入主库 gtid_purged,则无法正常补齐。
8.2. 从库已经拉取但未执行
Retrieved_Gtid_Set: uuid:1-100
Executed_Gtid_Set: uuid:1-80
含义:从库 IO 线程已经拉到 100,但 SQL 线程只执行到 80。此时应重点排查 SQL 线程状态、慢 SQL、锁等待和复制报错。
8.3. 从库多出事务
主库 gtid_executed: uuid_a:1-100
从库 Executed_Gtid_Set: uuid_a:1-100,uuid_b:1-5
含义:从库可能执行过本地写入事务,或曾经作为主库产生过事务。生产从库通常应避免本地写入,否则可能影响主从一致性和后续切换。
8.4. 主库已清理所需 binlog
从库缺失: uuid:50-60
主库 gtid_purged: uuid:1-80
含义:从库需要的 50-60 已被主库清理,无法从该主库继续复制。常见处理方向是重新搭建从库,或寻找仍保留该范围 binlog 的其他实例。
9. 常用 SQL 与函数
9.1. 查看 GTID 模式
SHOW VARIABLES LIKE 'gtid_mode';
SHOW VARIABLES LIKE 'enforce_gtid_consistency';
9.2. 查看当前实例 GTID 集合
SELECT @@GLOBAL.gtid_executed;
SELECT @@GLOBAL.gtid_purged;
9.3. 判断一个集合是否包含另一个集合
SELECT GTID_SUBSET('uuid:1-80', 'uuid:1-100');
返回 1 表示第一个集合是第二个集合的子集。
9.4. 计算集合差异
SELECT GTID_SUBTRACT('uuid:1-100', 'uuid:1-80');
返回结果:
uuid:81-100
该函数常用于判断从库缺少哪些事务。
10. 排查思路
10.1. 主从复制延迟
排查顺序:
- 查看
Retrieved_Gtid_Set是否继续增长。 - 查看
Executed_Gtid_Set是否继续增长。 - 如果只拉取不执行,检查 SQL 线程错误。
- 如果拉取也停止,检查 IO 线程、网络、账号权限和主库 binlog。
- 比较主库
gtid_executed与从库Executed_Gtid_Set。
10.2. GTID 缺失
排查顺序:
- 用
GTID_SUBTRACT()计算从库缺失范围。 - 检查缺失范围是否包含在主库
gtid_purged中。 - 如果未清理,尝试恢复复制线程。
- 如果已清理,评估重新搭建从库或寻找其他日志源。
10.3. 从库误写入
排查顺序:
- 比较主库与从库
gtid_executed。 - 找出从库多出的 server_uuid 范围。
- 判断是否为从库本地写入或历史主库切换遗留。
- 评估数据一致性影响。
- 修复后设置只读策略,例如
read_only与super_read_only。
11. 记忆口诀
gtid_executed:当前实例已经执行过的全部事务。gtid_purged:当前实例执行过但 binlog 已清理的事务。Retrieved_Gtid_Set:从库 IO 线程已经拉回 relay log 的事务。Executed_Gtid_Set:从库 SQL 线程已经执行完成的事务。
可以用“下载”和“执行”区分从库两个集合:
Retrieved = 下载完成
Executed = 执行完成
12. 面试回答模板
标准回答 GTID 是 MySQL 为每个事务生成的全局唯一编号,格式通常是
server_uuid:transaction_id。GTID 集合用于表达一批事务范围,例如uuid:1-100。主库上的gtid_executed表示已经执行过的事务集合,gtid_purged表示执行过但 binlog 已清理的事务集合;从库状态中的Retrieved_Gtid_Set表示 IO 线程已经拉取到 relay log 的事务,Executed_Gtid_Set表示 SQL 线程已经执行完成的事务。排查主从复制时,如果 Retrieved 增长而 Executed 不增长,通常是 SQL 线程执行问题;如果从库缺失事务已经落入主库 gtid_purged,则无法通过正常复制补齐,通常需要重建从库或寻找其他日志源。
关联文档
- MySQL 复制原理与配置:理解 GTID 复制链路和主从同步配置。
- MySQL GTID 主从故障排查:处理 GTID 缺失、跳过事务和复制中断问题。
- MySQL 主从同步故障排查:排查复制线程异常、延迟和数据不一致问题。
- MySQL binlog 保留时间与清理:理解
gtid_purged与 binlog 清理策略的关系。
