📝 本文首发于 栏轩·阁
欢迎访问阅读原文,获取更好的阅读体验。
1. 什么是 GTID?
GTID (Global Transaction Identifier,全局事务标识符)是 MySQL 5.6 引入的一项核心特性,它为每个在主库 上提交的事务生成一个全局唯一的标识符,并贯穿整个复制链路。
1.1 GTID 的格式
GTID = source_id:transaction_id
- source_id :发起事务的服务器 UUID(即
server_uuid,存储在auto.cnf中) - transaction_id:在该服务器上递增的序列号(从 1 开始)
示例:d2c5a7b1-3f4e-11ec-8d6a-00155d0a6c11:123
1.2 GTID 的生命周期
- 事务在主库提交时,分配一个 GTID
- GTID 随 binlog 传送给从库
- 从库应用该事务后,记录该 GTID 到自己的
gtid_executed集合中 - GTID 在整个复制拓扑中永不重复------同一 GTID 在任何节点上最多执行一次
2. 为什么需要 GTID?------ 与传统 File+Position 对比
2.1 传统 File+Position 复制的问题
在 GTID 出现之前,MySQL 主从复制依赖三个信息:
- binlog 文件名 (如
mysql-bin.000001) - binlog 偏移量 (如
157) - 主库的 server_id
| 痛点 | 说明 |
|---|---|
| 定位麻烦 | 从库必须精确记录主库的 File + Position,一旦出错或丢失,重建同步困难 |
| 主库切换困难 | 主库宕机后,新主库的 File+Position 发生变化,老从库难以找到断点继续同步 |
| 跳过事务危险 | SET GLOBAL sql_slave_skip_counter 跳过 N 个事务,极易跳出不一致 |
| 不支持多线程写入 | 多源复制(多主一从)几乎不可行 |
2.2 GTID 复制的优势
| 优势 | 说明 |
|---|---|
| 自动定位 | MASTER_AUTO_POSITION=1,从库自动计算需要同步的 GTID 集合,无需手动指定 File+Position |
| 主从切换极简 | 主库宕机后,将从库提升为新主库,其他从库只需指向新主库即可自动断点续传 |
| 一致性保证 | GTID 天然保证每个事务在集群内只执行一次,不会重复或遗漏 |
| 支持多源复制 | 一个从库可以同时从多个主库同步,因为 GTID 自带 source_id 区分来源 |
| 拓扑管理友好 | 可通过 gtid_executed 集合快速了解各节点的事务执行情况 |
2.3 对比一览表
| 特性 | File+Position | GTID |
|---|---|---|
| 复制定位方式 | 文件名 + 偏移量 | 全局唯一事务 ID |
| 主库切换便捷性 | 差(需找 File+Position) | 优(自动定位) |
| 操作复杂度 | 中等 | 低 |
| 多源复制支持 | 不支持 | 原生支持 |
| MySQL 最低版本 | 3.23+ | 5.6+ |
| 一致性风险 | 跳过事务可能不一致 | 自动跳过已执行事务 |
3. 前置知识
在学习和使用 GTID 集群之前,建议先掌握:
- MySQL 主从复制的基本原理与配置流程
- 使用 File+Position 方式搭建过主从集群
- 了解 binlog 的基本概念(ROW / STATEMENT / MIXED 格式)
- 基础的 MySQL 用户权限管理
4. GTID 配置实战
4.1 主从节点配置文件
在每个节点的 my.cnf / my.ini 中添加:
ini
# === GTID 核心配置 ===
gtid_mode = ON
enforce_gtid_consistency = ON
# === 服务器标识(每个节点唯一)===
server_id = 1 # 主从节点的 server_id 必须不同
log_bin = mysql-bin # 启用 binlog(从库作为 relay log,建议也开启)
binlog_format = ROW # 推荐使用 ROW 格式,与 GTID 配合最佳
skip_slave_start = 1 # 建议开启,避免启动时自动恢复复制
# === 可选推荐配置 ===
binlog_gtid_simple_recovery = ON # 加速 GTID 恢复(MySQL 5.7.7+ 默认开启)
log_slave_updates = ON # 从库将接收的事务写入自己的 binlog(级联复制必需)
expire_logs_days = 7 # binlog 自动清理
注意 :
enforce_gtid_consistency = ON强制所有事务都满足 GTID 安全要求,会阻止创建临时表等非事务性操作跨事务边界。
4.2 配置参数详解
| 参数 | 说明 |
|---|---|
gtid_mode = ON |
启用 GTID 模式。可选值:OFF / OFF_PERMISSIVE / ON_PERMISSIVE / ON |
enforce_gtid_consistency = ON |
强制 GTID 一致性,禁止非安全的语句 |
log_slave_updates = ON |
从库将同步的事务写入自己的 binlog,级联复制必需 |
binlog_gtid_simple_recovery = ON |
简化 GTID 恢复过程,提升重启速度 |
4.3 配置 GTID 升级流程(从传统模式迁移)
如果你已有 File+Position 集群,可以在线滚动升级到 GTID:
1. 在每个节点依次执行(先从库,再主库):
SET GLOBAL gtid_mode = OFF_PERMISSIVE;
SET GLOBAL gtid_mode = ON_PERMISSIVE;
2. 等待所有节点完成事务同步(检查各节点 gtid_owned 为空)
3. 在每个节点依次执行:
SET GLOBAL gtid_mode = ON;
4. 启用 enforce_gtid_consistency = ON
5. 修改 CHANGE MASTER 为 MASTER_AUTO_POSITION = 1
4.4 创建复制用户
在主库上执行:
sql
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
4.5 从库连接主库
传统方式的连接:
sql
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=157;
GTID 方式的连接(关键区别在于 MASTER_AUTO_POSITION = 1):
sql
-- 停止已有的同步(如果有)
STOP SLAVE;
-- 重置从库设置
RESET SLAVE;
-- 配置主库信息,关键参数是 MASTER_AUTO_POSITION = 1
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_PORT=3306,
MASTER_AUTO_POSITION = 1; -- 让 GTID 自动定位
-- MySQL 8.0 如需 caching_sha2_password,需:
-- GET_MASTER_PUBLIC_KEY = 1;
-- 启动同步
START SLAVE;
4.6 验证复制状态
sql
SHOW SLAVE STATUS\G
重点关注以下字段:
| 字段 | 期望值 | 说明 |
|---|---|---|
Slave_IO_Running |
Yes | IO 线程正常连接主库拉取 binlog |
Slave_SQL_Running |
Yes | SQL 线程正常应用 relay log |
Auto_Position |
1 | 关键标志:表示已启用 GTID 自动定位 |
Seconds_Behind_Master |
0 | 从库延迟(0 表示实时同步) |
Retrieved_Gtid_Set |
有值 | 已从主库获取的事务集合 |
Executed_Gtid_Set |
有值 | 已在从库执行的事务集合 |
5. GTID 核心机制深入
5.1 gtid_executed 与 gtid_purged
sql
-- 查看已执行的所有 GTID
SHOW VARIABLES LIKE 'gtid_executed';
-- 查看已清理的 GTID(已被 purge 的 binlog 中的事务)
SHOW VARIABLES LIKE 'gtid_purged';
gtid_executed:该节点上已执行过的所有 GTID 集合,持久化存储在mysql.gtid_executed表中gtid_purged:已经被 purge 的 binlog 中包含的 GTID 集合
自动定位的原理 :
当从库执行 START SLAVE 时,会将自己的 gtid_executed 发送给主库。主库计算差值,只发送从库缺失的事务。这完全省去了人工定位 File+Position 的麻烦。
5.2 GTID 模式下的复制协议
从库 → 主库: "我已经有这些 GTID: {uuid1:1-100, uuid2:1-50}"
主库 → 从库: "好的,你缺失 {uuid1:101-150},我发给你"
这个过程由 MASTER_AUTO_POSITION = 1 自动完成,不需要人工介入。
6. 故障切换场景分析
6.1 主库宕机:传统方式 vs GTID
传统 File+Position 切换步骤
sql
-- 1. 找新主库的当前 binlog 位置
SHOW MASTER STATUS;
-- 结果: File: mysql-bin.000003, Position: 875
-- 2. 在其他从库上手动指向新主库
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO
MASTER_HOST='new-master',
...
MASTER_LOG_FILE='mysql-bin.000003', -- 手动填写
MASTER_LOG_POS=875; -- 手动填写
START SLAVE;
GTID 切换步骤
sql
-- 1. 在一台从库上停止同步
STOP SLAVE;
RESET SLAVE;
-- 2. 指向新主库,无需关心位置!
CHANGE MASTER TO
MASTER_HOST='new-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_PORT=3306,
MASTER_AUTO_POSITION = 1; -- 自动定位!
START SLAVE;
对比可见,GTID 让主从切换从复杂的手动定位简化到只需更改 IP,大幅降低了运维复杂度。
6.2 GTID 切换的缺点
尽管 GTID 大幅简化了切换流程,但它仍然需要手动执行切换,没有自动故障检测与转移机制。解决方案:
| 方案 | 说明 |
|---|---|
| MHA(Master High Availability) | 经典的 MySQL 高可用方案,支持 GTID,可自动检测主库故障并提升新主库 |
| Orchestrator | 现代化的 MySQL 拓扑管理工具,提供自动化故障转移和 Web UI |
| InnoDB Cluster + MySQL Router | MySQL 官方解决方案,基于 Group Replication,实现自动故障转移 |
| ProxySQL | 中间件层读写分离,配合自动切换可实现透明故障转移 |
6.3 修复复制错误
跳过单个事务(不推荐,但应急可用)
sql
-- 查看当前出错的事务 GTID
SHOW SLAVE STATUS\G
-- 注入一个空事务来跳过
SET GTID_NEXT = 'source_id:transaction_id';
BEGIN;
COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;
注意:GTID 模式下严禁 使用
SET GLOBAL sql_slave_skip_counter = 1,这条语句在 GTID 模式下会直接报错。
7. 监控与管理
7.1 常用监控命令
sql
-- 查看 GTID 运行模式
SHOW VARIABLES LIKE 'gtid_mode';
-- 查看各节点的事务执行情况
SHOW MASTER STATUS\G -- 显示本机的 GTID 执行集合
SHOW SLAVE STATUS\G -- 显示复制状态与 GTID 信息
-- 查看从库实际接收和执行了哪些 GTID
SELECT * FROM mysql.gtid_executed;
-- 检查是否有 GTID 不一致
SHOW VARIABLES LIKE 'gtid_owned'; -- 非空 = 有未完成事务
7.2 健康检查最佳实践
sql
-- 检查复制是否正常(适合写入监控脚本)
SELECT
SERVICE_STATE AS 'IO_Thread',
LAST_ERROR_NUMBER AS 'Last_IO_Error_No',
LAST_ERROR_MESSAGE AS 'Last_IO_Error'
FROM performance_schema.replication_connection_status\G
SELECT
SERVICE_STATE AS 'SQL_Thread',
LAST_ERROR_NUMBER AS 'Last_SQL_Error_No',
LAST_ERROR_MESSAGE AS 'Last_SQL_Error'
FROM performance_schema.replication_applier_status_by_worker\G
8. 总结与建议
什么时候应该使用 GTID?
| 场景 | 推荐 |
|---|---|
| 新建集群 | ✅ 直接使用 GTID,没有理由再使用传统方式 |
| 现有传统集群 | ✅ 建议迁移到 GTID,支持在线滚动升级 |
| 需要多源复制 | ✅ 必须使用 GTID,传统方式不支持 |
| MySQL 5.6 以下版本 | ❌ 需要升级到 5.6+ |