GTID复制在跨云场景下有哪些坑?

话题来源: 跨云灾备架构设计:如何实现业务系统的高可用与异地容灾

朋友们,今天咱们不聊那些高大上的架构图,就聊点实在的。前几天,我帮一个哥们儿排查他们跨云MySQL同步的问题,好家伙,那叫一个酸爽。主库在阿里云,从库在腾讯云,用的就是GTID复制,理论上应该稳如老狗,结果半夜告警响个不停,复制断了!折腾到天亮才弄明白。所以今天,我就想掏心窝子跟大家唠唠,GTID复制这玩意儿,在跨云这个“异地恋”场景里,到底有多少你想不到的坑。

坑一:网络,那个最熟悉的“陌生人”

你可能觉得,不就是拉条专线或者VPN嘛,能有多大问题?嘿,问题就出在这个“觉得”上。GTID复制对网络延迟和抖动的敏感度,远超你的想象。

我哥们儿的场景,公网延迟看着也就30ms,好像还行?但跨云专线在高峰期的抖动,偶尔能给你蹦到200ms以上。MySQL复制线程(IO_THREAD)是个急性子,它等网络包等得不耐烦了,超时参数(比如slave_net_timeout)一触发,直接就撂挑子不干了,报告“主从连接断开”。

更绝的是,你以为调大超时参数就万事大吉了?太天真。参数调太大,从库半天没反应,主库那边堆积的binlog线程(Dump Thread)可能都把内存给撑爆了。这就好比快递员在你家门口等你签字,等了三小时你还没开门,他车上新接的快递都快堆到马路对面了。

我的土办法

后来我们怎么搞的呢?除了把slave_net_timeoutmaster_connect_retry这些参数根据实际网络质量谨慎调整外,更重要的是,在从库上写了个“看门狗”脚本。这脚本不干别的,就每隔一分钟检查一下SHOW SLAVE STATUS里的Slave_IO_Running是不是Yes。一旦发现是Connecting或者No,并且错误信息是网络超时类的,它不会傻乎乎地直接重启复制(可能会造成重复事务),而是先记录,然后尝试自动重连几次。如果还不行,再告警叫人。这招虽然土,但真能救急。

坑二:GTID的“身份”危机

GTID的本意是让复制位置全局唯一,多省心啊。但跨云的时候,这个“全局”可能就变成了“局部”。

最经典的场景:初始化搭建。你从主云A导出一份全量备份,恢复到备云B的从库上。这份备份里,是带着主库A的GTID执行历史(gtid_executed)的。然后你在B从库上执行CHANGE MASTER TO ... MASTER_AUTO_POSITION=1,心想开启自动定位美滋滋。

结果呢?从库B一看自己本地已经执行过的GTID集合(就是备份里带的那些),再跟主库A一说:“老大,给我从这个GTID之后的数据吧。” 主库A懵了:“兄弟,你这GTID集合里有些事务的UUID(server_uuid)不是我生成的啊,我这儿没有这些记录,我怎么给你‘之后’的数据?” 得,复制直接报错,告诉你GTID集合有缺口(GTID gap)。

“Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: ‘The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.’”

看见没?是不是头皮发麻?解决办法就是在恢复备份后,必须执行一下RESET MASTER;(在从库上执行,安全的)来清空从库本地的GTID执行历史,告诉它:“忘掉过去,一切从零开始跟主库学。” 或者,用mysqldump备份时加上--set-gtid-purged=OFF参数,从源头上就不带GTID信息。

坑三:云厂商的“小动作”

这个坑隐蔽,但杀伤力巨大。不同云厂商的MySQL托管服务(RDS),底层对GTID和binlog的处理可能有“优化”或者“魔改”。

比如,有的厂商默认会开启binlog压缩,有的对binlog_expire_logs_seconds(binlog保留时间)有自己强制的策略,比你设的值更激进。在跨云复制延迟较大的情况下,主云的binlog可能因为空间策略被提前清理(purge)了。当从云好不容易追上来,跟主库要一个很早的GTID对应的binlog文件时,主库两手一摊:“抱歉,你要的历史资料,我们已经按规定销毁了。” 得,复制又断了,而且这种断是数据丢失性质的,无法自动恢复,只能从头重建。

还有更绝的,某些云厂商的只读实例或者特定版本,可能会在后台悄悄做一些你不知道的操作,甚至生成自己的GTID事务。这些“幽灵事务”混进GTID流里,等你哪天想切换或者搭建级联复制时,就能让你体会到什么叫“剪不断,理还乱”。

怎么防?

没啥捷径,就是读文档做测试。把两边云数据库的GTID相关参数、binlog策略、版本差异仔仔细细对一遍。上生产前,老老实实用接近真实数据量和网络环境做一次全流程的演练,从搭建、压测、模拟网络抖动到模拟切换,把所有可能的报错都在测试环境里见一遍。这笔时间成本,绝对比线上出问题后熬夜赔钱要划算得多。

写在最后

GTID复制是个好东西,它让数据同步的逻辑变得清晰。但跨云就像给这段关系加了“异地”和“不同文化背景”的Debuff。你不能指望它像在同一个机房内网里那样“傻白甜”地工作。

说白了,搞跨云GTID复制,你得同时扮演网络工程师、数据库专家和“婚姻”调解员。多监控,别光看Seconds_Behind_Master,更要关注IO线程状态和错误日志;参数调优要因地制宜,没有银弹;对云厂商的“特性”保持敬畏和怀疑。

那天帮我哥们儿搞定之后,我俩对着屏幕上的“Slave_IO_Running: Yes”发了半天呆。他点了根烟,说了句:“这哪是技术活,这简直是修行。” 我深以为然。

评论

  • 跨云专线抖动这个太真实了,我们之前也被坑过,半夜爬起来切流量。