必须五步渐进切换gtid模式:enforce_gtid_consistency=warn→on→gtid_mode=off_permissive→on_permissive→on,所有节点严格同步执行并验证状态,否则直接设on会报错或导致sql线程卡死。

确认所有节点已同步完成GTID五步切换
没走完五步就切,gtid_mode = ON会直接报错或导致从库SQL thread卡死。必须在主库和所有从库上**严格按顺序、逐节点执行**:enforce_gtid_consistency = WARN → ON → gtid_mode = OFF_PERMISSIVE → ON_PERMISSIVE → ON。
每步执行后,检查:SELECT @@global.gtid_mode, @@global.enforce_gtid_consistency;等待至少 1–2 分钟,再查SHOW SLAVE STATUS\G确认无Last_IO_Error或Last_SQL_Error;最后确认所有节点Auto_Position字段为1。
- 跳过任意一步(尤其
WARN阶段),应用中含CREATE TABLE ... SELECT或LOAD DATA INFILE等语句时,后续START SLAVE会失败 -
OFF_PERMISSIVE阶段必须等所有匿名事务自然消耗完——可通过SELECT @@global.gtid_executed对比主从,若主库仍含0-0-开头的GTID,说明还有残留匿名事务 - 不要用脚本批量并发执行五步命令,节点间必须串行且人工校验
切换前必须验证GTID集合完全一致
仅看Seconds_Behind_Master = 0不够,GTID模式下真正要对齐的是Executed_Gtid_Set。主库执行SELECT @@global.gtid_executed,从库执行相同语句,再用GTID_SUBSET(master_gtid, slave_gtid)和GTID_SUBSET(slave_gtid, master_gtid)双向验证——两个都返回1才算真正一致。
常见错误:误把Retrieved_Gtid_Set当Executed_Gtid_Set比对,前者只是拉到但未执行的GTID,后者才是已落地的。一旦漏掉未执行的GTID,切换后新主库就会丢数据。
- 如果
GTID_SUBSET返回0,说明有GTID未执行,需先STOP SLAVE再等Seconds_Behind_Master归零,不能硬切 - 主库宕机无法连上?从库
SHOW MASTER STATUS拿到当前File/Position,用mysqlbinlog --base64-output=decode-rows -v解析对应binlog,人工核对最后几条事务是否已在从库gtid_executed中
提升从库为新主库时必须RESET SLAVE ALL + 关read_only
RESET SLAVE不行,它不删relay-log.info和中继日志文件,下次START SLAVE可能读错位点;read_only = ON不关,新主库写入会被拒绝——这两步漏一,切换就卡在“能连不能写”或“写完不同步”。
标准操作链:STOP SLAVE → RESET SLAVE ALL → SET GLOBAL read_only = OFF → SET GLOBAL super_read_only = OFF(如启用)→ 立即SELECT @@read_only确认返回0。
-
RESET SLAVE ALL后务必检查datadir下是否还剩relay-bin.*文件,残留文件可能干扰后续binlog解析 - 某些版本
super_read_only默认开启,只关read_only不够,必须显式关掉super_read_only - 切完立刻在新主库建一条测试记录:
INSERT INTO test_switch VALUES (NOW());,别等应用流量进来再验证
原主库重配复制时必须用MASTER_AUTO_POSITION=1
GTID模式下硬编码MASTER_LOG_FILE和MASTER_LOG_POS是自找麻烦——位置随时变,且容易因relay log残留导致CHANGE MASTER TO指向错误偏移。唯一可靠方式是MASTER_AUTO_POSITION = 1,让MySQL自动匹配GTID。
操作顺序:STOP SLAVE → CHANGE MASTER TO MASTER_HOST='新主IP', MASTER_USER='repl', MASTER_PASSWORD='xxx', MASTER_AUTO_POSITION = 1 → START SLAVE → 立即查SHOW SLAVE STATUS\G看Slave_IO_Running和Slave_SQL_Running是否均为Yes,且Retrieved_Gtid_Set开始增长。
- 如果
START SLAVE后Seconds_Behind_Master一直为NULL,大概率是MASTER_AUTO_POSITION = 1没生效,检查CHANGE MASTER TO语句里有没有漏掉=1或写成=ON - 原主库切回来做从库后,
gtid_purged可能残留旧主库的GTID,需先RESET MASTER(仅限无其他从库依赖该实例时)或手动SET GLOBAL gtid_purged = '新主库的gtid_executed值'
OFF_PERMISSIVE阶段的匿名事务清空等待,以及RESET SLAVE ALL后对残留relay log的手动清理。











