加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.ijishu.cn/)- CDN、边缘计算、物联网、云计算、开发!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

GTID复制卡顿?5年实战教你秒切主从避坑

发布时间:2026-10-09 22:18:58 所属栏目:MySql教程 来源:DaWei
导读:凌晨三点四十二分,监控大屏上的主从延迟数字像发了疯的兔子一样从零点三秒蹦到了两百四十秒,我盯着那根红线,手里的冰美式早就凉透了。DBA老张把键盘敲得噼啪响,眉头皱得能夹死苍蝇,他指着屏幕吼道这破库是不是又死锁了,语
凌晨三点四十二分,监控大屏上的主从延迟数字像发了疯的兔子一样从零点三秒蹦到了两百四十秒,我盯着那根红线,手里的冰美式早就凉透了。
DBA老张把键盘敲得噼啪响,眉头皱得能夹死苍蝇,他指着屏幕吼道这破库是不是又死锁了,语气里全是那种被半夜叫醒的烦躁和无奈。我没接话,直接登录跳板机,用 `show slave status\\G` 拉出状态,一眼就看见 `Seconds_Behind_Master` 那个字段红得刺眼,而 `Last_SQL_Error` 居然是空的,这说明SQL线程没报错,只是在空转或者等待,这种静默的卡顿简直比报错更让人心里发毛。
GTID复制模式下的卡顿根本就不是网络抖动那么简单。
上周二下午两点,我在测试环境复现了这个场景,故意往主库灌入五千条带有大事务的更新语句,从库的 `relay_log_space_limit` 设成了两G,结果 relay log 还没写满,IO线程就因为磁盘写入瓶颈卡住了半分钟,这时候主库还在疯狂推送 binlog,导致从库的 `exec_master_log_pos` 和 `read_master_log_pos` 之间的差距迅速拉大到八百多兆。
二零一九年我刚入行那会儿,还在用基于 position 的老式复制,那时候遇到同步慢,我们要么重启从库,要么手动跳过错误事务,有一次为了追平数据,我硬是等了六个半小时,期间不敢动任何配置,生怕数据错乱,那种被动等待的日子现在想起来都觉得憋屈。

文章配图,仅供参考

现在的 GTID 虽然解决了故障切换时的位点寻找问题,但它对事务提交的原子性要求更高,一旦主库出现大事务或者从库硬件IO跟不上,整个复制链路就会因为等待上一个 GTID 事务集确认而阻塞,这绝对是个设计上的权衡陷阱。
别信什么自动优化参数能解决一切。
我查了 `performance_schema` 里的 `events_waits_summary_global_by_event_name` 表,发现 `wait/synch/cond/sql/SLAVE_worker_0` 这个等待事件占比高达百分之七十,这意味着 worker 线程在争抢资源,而不是在网络传输上浪费时间。老张凑过来看了一眼,撇撇嘴说肯定是索引没建好,他随手点了根烟,眼神里带着那种老油条特有的笃定,仿佛只要加了索引世界就和平了。
我当场就在从库跑了个 `explain`,执行计划显示全表扫描,但这解释不了为什么主库不卡而从库卡,因为主库有查询缓存和更好的内存池,而从库为了保持数据一致性,回放 SQL 时往往无法充分利用这些加速机制。
切主从不是点一下鼠标的事。
昨晚十一点,生产环境再次报警,这次我决定不再等它自愈,而是执行秒级切换。我先在主库执行 `SET GLOBAL read_only = ON`,确保没有新写入,然后观察从库的 `Retrieved_Gtid_Set` 和 `Executed_Gtid_Set` 是否完全一致,这两个集合必须严丝合缝,差一个字符都不能切。
我用 `pt-heartbeat` 工具监测到的延迟是零点零五秒,这时候才敢动手。很多人以为 GTID 模式下直接提升从库就行,其实如果不检查 `gtid_purged`,新主库可能会拒绝接受旧主库回传的数据,导致脑裂。
当年的我们哪懂这些,二零二零年那次迁移,我们三个人熬了两个通宵,手动比对了一万三千条核心订单数据,用 Excel 表格一个个勾兑,累得眼睛充血,现在想想简直是原始社会的劳作方式。
切换命令输下去的那几秒,心跳都快停了。
`CHANGE MASTER TO` 执行完,新主库的 `server_id` 变了,应用层的连接池开始重连,我看到监控上的 QPS 曲线跌了一个深坑,然后在十五秒内迅速回升到正常水平,这个过程里没有任何数据丢失,binlog 文件号从 mysql-bin.000421 跳到了 000422,一切看似平静,但我知道底层的数据页刚刚经历了一场剧烈的重组。
老张在旁边打了个哈欠,说这就完了?他显然没意识到刚才那几十秒里,我们避开了多少个可能导致数据不一致的深坑。
GTID 不是银弹,它只是把复杂度从运维转移到了内核层面。
如果你看到 `slave_parallel_workers` 设为四,但 CPU 利用率只有百分之二十,那绝对是并行回放策略没配好,或者是事务之间依赖性太强导致无法并行。我去查了 `binlog_transaction_dependency_tracking` 的配置,发现它还是默认的 `COMMIT_ORDER`,改成 `WRITESET` 后,从库的吞吐量直接提升了三倍,这个数字不会骗人。
别再盯着 `Seconds_Behind_Master` 看了,那玩意儿在高并发下就是个笑话。
真正的瓶颈藏在 `sys.innodb_lock_waits` 里,我昨晚抓到了一个持续了十二秒的行锁等待,源头居然是一个名为 `tmp_user_info_bak` 的临时表,这是三年前某个离职同事留下的烂代码,每次同步都要锁住主键索引,这种历史遗留问题简直堪称定时炸弹。
现在的主库已经稳定运行了四个小时,延迟始终维持在零点一秒以内。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!