开头说明:GTIDs 与 GTID 的区别
- GTID(Global Transaction Identifier):全局事务标识符,是单个事务的唯一标识,格式为
UUID:事务ID(例如a1b2c3d4-1234-5678-90ab-cdef01234567:5)。每个事务在主库执行时会被分配一个唯一 GTID,从库通过 GTID 确认已执行的事务,避免重复执行。 - GTIDs:是 GTID 的复数形式,通常指 “GTID 机制” 或 “一组 GTID 事务集合”,用于描述基于 GTID 的复制架构整体特性,而非单个事务标识。
简单来说:GTID 是单个事务的 “身份证”,GTIDs 是这套 “身份证系统” 的统称,日常配置和沟通中两者常被混用,但核心语义需区分 —— 前者指向具体事务,后者指向整体机制。
一、背景介绍:为什么需要 GTID 复制?
传统主从复制依赖 “二进制日志文件名 + 位置” 定位同步起点,存在明显痛点:
- 主从切换时需手动记录新主库的日志文件和位置,易出错;
- 复制中断后,需手动对比主从日志找到同步断点,排查效率低;
- 级联复制(主→从→从)场景下,断点定位复杂,维护成本高。
GTID 复制作为 MySQL 5.6 + 引入的增强特性,完美解决了上述问题:
- 自动定位同步起点:从库通过 GTID 自动识别已执行的事务,无需手动指定日志文件和位置;
- 简化主从切换:故障转移时,新主库的 GTID 集合可直接被从库复用,无需额外配置;
- 事务级别的一致性:每个事务对应唯一 GTID,便于跟踪和排查复制问题;
- 支持幂等性:从库不会重复执行已完成的 GTID 事务,提升复制稳定性。
本文基于已搭建的传统 MySQL 主从复制环境(CentOS 7+MySQL 5.7),详细讲解如何升级到 GTID 复制架构,包含配置、验证、测试和故障处理,适合需要提升主从复制可用性的运维工程师和开发人员。
二、核心关键词解释
- GTID(全局事务标识符):全局唯一的事务 ID,格式为
UUID:事务序列号,主库生成后随事务同步到从库,作为事务执行状态的标识; - gtid_mode:GTID 模式开关,取值为
ON(启用)、OFF(禁用)、ON_PERMISSIVE(过渡启用)、OFF_PERMISSIVE(过渡禁用),生产环境需设为ON; - enforce_gtid_consistency:强制 GTID 一致性,确保所有事务都符合 GTID 规则(如禁止不支持 GTID 的 SQL 语句),必须设为
ON; - log-slave-updates:允许从库将同步的事务写入自身二进制日志,级联复制(从库作为其他从库的主库)时必需;
- MASTER_AUTO_POSITION=1:从库启用 GTID 自动定位模式,无需指定主库的日志文件和位置,自动通过 GTID 匹配同步起点;
- gtid_executed:MySQL 系统表中记录的已执行 GTID 事务集合,主从同步成功后,从库的该集合应与主库一致。
三、GTID 复制的前提条件(必满足)
- 存储引擎限制:所有表必须使用 InnoDB,不支持 MyISAM(MyISAM 不支持事务,无法生成 GTID);
- SQL 语句限制:不支持
CREATE TABLE ... SELECT、临时表的CREATE/DROP操作,需提前修改相关业务 SQL; - 参数限制:必须启用
enforce-gtid-consistency=ON,禁止使用sql-slave-skip-counter跳过错误(GTID 模式下该参数失效); - 环境要求:MySQL 5.6 及以上版本(推荐 5.7+,稳定性更高),已搭建传统主从复制环境或全新环境;
- 一致性要求:主从数据需提前同步一致(升级前确保传统复制无延迟,避免 GTID 事务冲突)。
四、搭建普通主从复制架构(基础准备)
如果想要直接基于GTID搭建主从复制,可参考文章,同时本文也不需要看了
直接搭建 MySQL GTID 主从复制
https://blog.youkuaiyun.com/yifengyiyufjq/article/details/154988699
若尚未搭建传统主从复制环境,但是想在基于主从复制的基础上升级为基于GTID的主从复制,详细步骤参考文章,完成后再来继续下面的操作即可:MySQL 主从复制搭建全攻略(非 Docker 部署)
https://blog.youkuaiyun.com/yifengyiyufjq/article/details/154427329?spm=1011.2124.3001.6209
核心要点(确保已完成):
- 主库(192.168.238.134)已开启二进制日志(
log-bin=mysql-bin),server-id=10; - 从库(192.168.238.133)已配置中继日志(
relay-log=/var/lib/mysql/relaylog),server-id=100; - 主从网络互通,3306 端口可访问,已创建复制用户(
repl_user)并授予REPLICATION SLAVE权限; - 主从数据一致,传统复制状态正常(
Slave_IO_Running=Yes、Slave_SQL_Running=Yes)。
五、升级到 GTID 复制架构(核心步骤)
1. 配置主服务器(192.168.238.134)
步骤 1:修改配置文件 my.cnf(添加 GTID 核心配置)
bash
运行
# 编辑主库MySQL配置文件
vim /etc/my.cnf
配置内容(保留原有配置,新增 GTID 相关参数):
ini
[mysqld]
# 基础路径与日志配置(原有)
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
port=3306
# 原有主从复制配置
log-bin=mysql-bin # 开启二进制日志(主库必需)
server-id=10 # 主库唯一ID(与从库不同)
binlog_format=ROW # 日志格式(ROW模式,支持GTID)
expire_logs_days=7 # 日志过期时间
character-set-server=utf8mb4 # 字符集
collation-server=utf8mb4_unicode_ci
# 新增GTID核心配置(关键)
gtid-mode=on # 启用GTID模式
enforce-gtid-consistency=ON # 强制GTID一致性(禁止不支持的SQL)
log-slave-updates=1 # 级联复制必需(从库同步的事务写入自身binlog)
步骤 2:重启主库并验证配置
bash
运行
# 重启MySQL服务(使配置生效)
service mysqld restart
# 验证服务状态(确保启动成功,避免配置错误导致启动失败)
service mysqld status
# 登录MySQL验证GTID参数(需返回ON,说明配置生效)
mysql -uroot -p -e "show variables like 'gtid_mode'; show variables like 'enforce_gtid_consistency';"
- 若启动失败,查看错误日志:
cat /var/log/mysqld.log,排查配置文件语法错误或参数冲突。
步骤 3:创建复制用户(若未创建)
若传统主从复制已创建repl_user,可跳过此步骤;若未创建,执行以下命令:
bash
运行
# 登录主库MySQL(使用root密码)
mysql -uroot -p
执行 SQL(创建仅允许从库 IP 访问的复制用户):
sql
-- 创建复制用户(指定从库IP 192.168.238.133,增强安全性)
CREATE USER 'repl_user'@'192.168.238.133' IDENTIFIED BY 'YourPassword123!'; # 替换为复杂密码
-- 授予复制权限(最小权限原则,仅授予REPLICATION SLAVE)
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.238.133';
-- 刷新权限使配置生效
FLUSH PRIVILEGES;
2. 配置从服务器(192.168.238.133)
步骤 1:修改配置文件 my.cnf(添加 GTID 配置)
bash
运行
# 编辑从库MySQL配置文件
vim /etc/my.cnf
配置内容(保留原有配置,新增 GTID 参数):
ini
[mysqld]
# 基础路径与日志配置(原有)
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
port=3306
# 原有从库配置
relay-log=/var/lib/mysql/relaylog # 中继日志路径
log-bin=mysql-bin # 级联复制需开启(从库作为其他从库的主库)
server-id=100 # 从库唯一ID(与主库不同)
binlog_format=ROW # 与主库保持一致
expire_logs_days=7 # 日志过期时间
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
# 新增GTID核心配置(关键)
gtid-mode=on # 启用GTID模式
enforce-gtid-consistency=ON # 强制GTID一致性
log-slave-updates=1 # 级联复制必需(若无需级联可设为0,但建议开启)
步骤 2:重启从库并验证配置
bash
运行
# 重启MySQL服务
service mysqld restart
# 验证服务状态(确保启动成功)
service mysqld status
# 登录MySQL验证GTID参数(需返回ON)
mysql -uroot -p -e "show variables like 'gtid_mode'; show variables like 'enforce_gtid_consistency';"
3. 临时设置只读模式(主从均执行)
为避免升级过程中主库写入新数据导致 GTID 事务冲突,临时开启只读模式:
bash
运行
# 主库执行(仅限制普通用户写入,root用户不受影响)
mysql -uroot -p -e "SET @@global.read_only=ON;"
# 从库执行(同上)
mysql -uroot -p -e "SET @@global.read_only=ON;"
# 验证只读模式(返回ON即为成功)
mysql -uroot -p -e "SHOW VARIABLES LIKE 'read_only';"
4. 重新配置从服务器复制关系(核心升级步骤)
传统复制依赖 “日志文件 + 位置”,GTID 复制需改为 “自动定位”,需重置从库复制配置:
bash
运行
# 登录从库MySQL(使用从库root密码)
mysql -uroot -p
执行 SQL(配置 GTID 模式的主从连接):
sql
-- 1. 停止现有传统复制进程
STOP SLAVE;
-- 2. 重置复制配置(清空旧的日志文件、位置信息和主库连接信息)
RESET SLAVE ALL;
-- 3. 配置GTID模式的主从连接(无需指定日志文件和Position)
CHANGE MASTER TO
MASTER_HOST='192.168.238.134', # 主库IP地址
MASTER_USER='repl_user', # 主库创建的复制用户
MASTER_PASSWORD='YourPassword123!', # 复制用户密码(与主库一致)
MASTER_PORT=3306, # 主库端口(默认3306)
MASTER_AUTO_POSITION=1; # 启用GTID自动定位(关键参数)
-- 4. 启动GTID模式的复制进程
START SLAVE;
六、验证 GTID 复制状态(关键步骤)
1. 检查从库复制状态
在从库 MySQL 终端执行以下命令,验证 GTID 复制是否配置成功:
sql
-- 查看从库复制详细状态(\G表示纵向显示,便于查看关键参数)
SHOW SLAVE STATUS\G
需确认以下核心项(全部满足即为成功):
Slave_IO_Running: Yes:从库 IO 线程正常(成功连接主库并获取 GTID 事务);Slave_SQL_Running: Yes:从库 SQL 线程正常(成功执行 GTID 事务);Auto_Position: 1:GTID 自动定位已启用(区别于传统复制的 0);Retrieved_Gtid_Set:已从主库拉取的 GTID 事务集合(非空);Executed_Gtid_Set:已在从库执行的 GTID 事务集合(与主库gtid_executed一致);Seconds_Behind_Master: 0:从库无同步延迟(实时同步)。
2. 关闭只读模式(恢复业务读写)
验证 GTID 复制状态正常后,关闭主从的临时只读模式:
bash
运行
# 主库执行(恢复写操作)
mysql -uroot -p -e "SET @@global.read_only=OFF;"
# 从库执行(恢复写操作,若从库需只读可保持ON)
mysql -uroot -p -e "SET @@global.read_only=OFF;"
# 验证(返回OFF即为成功)
mysql -uroot -p -e "SHOW VARIABLES LIKE 'read_only';"
七、测试 GTID 复制功能(验证可用性)
通过在主库写入数据,验证从库是否能通过 GTID 正常同步:
1. 主服务器写入测试数据
登录主库 MySQL,执行以下 SQL 创建测试数据:
sql
-- 1. 创建测试数据库
CREATE DATABASE gtid_test;
USE gtid_test;
-- 2. 创建测试表(必须使用InnoDB引擎,符合GTID要求)
CREATE TABLE test_gtid (
id INT AUTO_INCREMENT PRIMARY KEY,
data VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB COMMENT='GTID复制测试表';
-- 3. 插入测试数据(触发2个GTID事务)
INSERT INTO test_gtid (data) VALUES ('GTID测试数据1');
INSERT INTO test_gtid (data) VALUES ('GTID测试数据2');
-- 4. 查看主库GTID状态(确认事务已生成GTID)
SHOW MASTER STATUS; # 查看当前GTID集合
SELECT * FROM mysql.gtid_executed; # 查看已执行的GTID事务(包含上述2条插入事务)
2. 从服务器验证同步结果
登录从库 MySQL,执行以下 SQL 验证数据同步:
sql
-- 1. 检查测试库是否同步
SHOW DATABASES LIKE 'gtid_test'; # 应返回gtid_test库(同步成功)
-- 2. 查看测试数据(验证数据一致性)
USE gtid_test;
SELECT * FROM test_gtid; # 应显示主库插入的2条数据
-- 3. 查看从库GTID状态(验证GTID一致性)
SHOW SLAVE STATUS\G # 确认Retrieved_Gtid_Set和Executed_Gtid_Set包含主库的GTID
SELECT * FROM mysql.gtid_executed; # 与主库的gtid_executed集合完全一致
若从库能正常查询到测试数据,且 GTID 集合与主库一致,说明 GTID 复制功能正常!
八、故障处理与维护(避坑指南)
1. 跳过 GTID 错误事务
GTID 模式下禁止使用sql-slave-skip-counter,若从库复制出错(如事务冲突),需通过以下方式跳过错误 GTID:
sql
-- 1. 查看错误详情(获取出错的GTID,例如:a1b2c3d4-1234-5678-90ab-cdef01234567:5)
SHOW SLAVE STATUS\G # 错误信息在Last_Error字段,GTID在Retrieved_Gtid_Set中
-- 2. 停止复制进程
STOP SLAVE;
-- 3. 手动跳过指定错误GTID(替换为实际出错的GTID)
SET GTID_NEXT='a1b2c3d4-1234-5678-90ab-cdef01234567:5'; # 示例GTID,需替换
BEGIN; # 开启空事务
COMMIT; # 提交空事务(相当于标记该GTID已执行)
SET GTID_NEXT='AUTOMATIC'; # 恢复GTID自动分配模式
-- 4. 重启复制进程
START SLAVE;
-- 5. 验证状态(确认错误已解决)
SHOW SLAVE STATUS\G
- 注意:仅当错误事务不影响数据一致性时(如重复插入),才可跳过;若为数据冲突,需先修复数据再跳过。
2. 查找错误 GTID 的方法
若不确定出错的 GTID 对应的事务,可通过解析中继日志定位:
bash
运行
# 1. 进入MySQL二进制日志工具目录
cd /usr/local/mysql/bin
# 2. 解析从库中继日志(替换为实际中继日志文件,如relaylog.000003)
./mysqlbinlog /var/lib/mysql/relaylog.000003 | grep -A 10 -B 5 "ERROR"
- 输出结果中会显示错误位置对应的 GTID 和 SQL 语句,便于排查问题(如 SQL 语法错误、数据约束冲突)。
3. 完全重新同步(复制无法修复时)
若 GTID 复制出现严重错误(如主从 GTID 集合不一致),需重新同步数据:
主库操作(导出全量数据,包含 GTID 信息):
bash
运行
# 1. 导出全量数据(--gtid参数包含GTID信息,确保从库同步时识别已执行事务)
mysqldump -uroot -p --all-databases --single-transaction --flush-logs --master-data=2 --gtid --events > /tmp/fulldump_gtid.sql
# 2. 将备份文件传输到从库(替换为从库IP)
scp /tmp/fulldump_gtid.sql root@192.168.238.133:/tmp/
从库操作(导入数据并重新配置 GTID 复制):
bash
运行
# 1. 停止复制并重置配置
mysql -uroot -p -e "STOP SLAVE; RESET SLAVE ALL;"
# 2. 导入全量数据(覆盖从库现有数据,确保与主库一致)
mysql -uroot -p < /tmp/fulldump_gtid.sql
# 3. 重新配置GTID复制(无需指定日志文件和位置)
mysql -uroot -p -e "CHANGE MASTER TO MASTER_HOST='192.168.238.134', MASTER_USER='repl_user', MASTER_PASSWORD='YourPassword123!', MASTER_AUTO_POSITION=1; START SLAVE;"
# 4. 验证同步状态
mysql -uroot -p -e "SHOW SLAVE STATUS\G"
九、GTID 监控与管理(日常维护)
1. 常用监控命令
sql
-- 查看GTID相关参数(确认配置未被修改)
SHOW GLOBAL VARIABLES LIKE '%gtid%';
-- 查看主库已执行的GTID事务集合
SELECT * FROM mysql.gtid_executed;
-- 查看从库复制状态(重点关注GTID相关字段)
SHOW SLAVE STATUS\G
-- 查看主库当前GTID状态
SHOW MASTER STATUS;
-- 查看从库已拉取和执行的GTID
SELECT @@global.gtid_retrieved; # 已拉取的GTID集合
SELECT @@global.gtid_executed; # 已执行的GTID集合
2. 关键参数说明
| 参数名称 | 取值 | 作用说明 |
|---|---|---|
| gtid_mode | ON | 启用 GTID 模式(生产环境必需) |
| enforce_gtid_consistency | ON | 强制事务符合 GTID 规则,禁止不支持的 SQL |
| gtid_executed | 事务集合 | 已执行的 GTID 事务(主从同步成功后需一致) |
| gtid_purged | 事务集合 | 已清除的 GTID 事务(日志过期后会被清理,不可恢复) |
| log_slave_updates | 1/0 | 1:从库同步的事务写入自身 binlog(级联复制必需);0:不写入 |
十、重要注意事项
- server-id 唯一性:主从服务器的
server-id必须唯一(主库 10,从库 100),否则会导致复制失败; - 存储引擎限制:所有业务表必须使用 InnoDB,若存在 MyISAM 表,需通过
ALTER TABLE 表名 ENGINE=InnoDB;转换; - 级联复制配置:若从库需作为其他从库的主库(级联复制),必须开启
log-bin和log-slave-updates=1; - 操作时机:升级 GTID 需在业务低峰期执行,提前用
mysqldump备份全量数据,避免数据丢失; - 禁止的操作:GTID 模式下禁止使用
sql-slave-skip-counter、CREATE TABLE ... SELECT、临时表的CREATE/DROP,需提前梳理业务 SQL; - 验证标准:
- 主从
gtid_mode和enforce_gtid_consistency均为 ON; - 从库
Auto_Position=1,Slave_IO_Running和Slave_SQL_Running均为 Yes; - 测试数据同步成功,主从
gtid_executed集合一致。
- 主从
十一、总结
GTID 复制通过 “全局唯一事务 ID” 替代传统的 “日志文件 + 位置”,大幅简化了主从复制的配置、切换和维护成本,是生产环境的首选方案。
搭建核心流程:满足 GTID 前提条件→升级主从配置文件(启用 GTID 参数)→重置从库复制关系(启用自动定位)→验证同步状态→测试功能可用性。
日常维护中,需重点监控Slave_IO_Running、Slave_SQL_Running和 GTID 集合一致性,遇到错误时通过解析日志定位问题,避免盲目跳过事务。通过本文步骤,可快速将传统主从复制升级为稳定、易维护的 GTID 复制架构。
285

被折叠的 条评论
为什么被折叠?



