
有事务冲突时节点怎么加入MGR集群
1. 问题场景描述
2. 如何修复
2.1 找出事务差异点
2.2 决定如何处理
3. 小结
个别节点可能存在事务冲突,导致无法加入MGR集群,该怎么处理?
1. 问题场景描述
有些时候,可能因为网络分区等异常情况导致节点意外退出MGR集群,在退出之前可能有些事务还没来得及发送到其他节点。或者可能因为误操作,在这个节点上意外写入数据。那么这个节点重加入MGR集群时,就可能会报告类似下面的错误:
这段日志的意思是,本地节点的事务GTID为 1-300917674,而欲加入的MGR集群的事务GTID是 1-300917669,本地节点多了5个事务,因此无法正确加入。
2. 如何修复
遇到这种报错不要慌,我们一起来看下怎么处理。大致可以分为X步走。
2.1 找出事务差异点
首先,根据报错日志,找出本地节点相对于MGR集群多出来的或有差异的事务。在本案中,本地节点多了5个事务,利用mysqlbinlog来看这些事务都涉及到哪些数据对象:
接下来就可以对解析出来的SQL文件进行检查,判断影响了哪些数据对象,以及具体哪些数据。
此时,如果MySQL已经设置了 binlog_rows_query_log_events = ON*(这个选项默认值是 OFF,建议改成开启),则binlog里还会记录原始SQL语句,更方便排查了,例如这样:
2.2 决定如何处理
现在已经知道本地节点和MGR集群相差了哪些数据,就需要进行选择了,看看是要舍弃这些事务数据,还是人工补差。
如果是选择舍弃差异的事务数据,则需要在本地节点对有差异的数据进行回滚,原来是INSERT的数据改成DELETE,原来是DELETE的数据改成INSERT,把新值UPDATE成旧值。也可以利用第三方闪回工具进行恢复。
完成事务回滚后,在MGR集群某个节点执行下面的SQL,查看当前的GTID信息:
复制上面的GTID信息,在欲重新加入MGR的节点上执行下面的SQL命令:
之后应该就可以直接启动MGR服务,重新加回MGR集群了。
如果是选择手动补足差异的事务数据,首先也是参考上面的方法,解析binlog导出相对应的事务,确认要补差的事务数据。然后执行类似下面的命令,把本地节点多出来的事务应用到MGR集群的Primary节点上,例如下面这样:
补差的事务应用完毕后,再检查两边的GTID差异,然后同样也要执行 RESET MASTER 以及修改 GTID_PURGED 的工作,之后再启动MGR服务即可。
不过,在补完差异数据后,可以直接利用clone重建Secondary实例,再加入MGR集群即可,就不用再手动修改GTID这些麻烦且易错的操作了。在执行clone时,如果数据量较大,也要注意设置选项 clone_max_data_bandwidth 和 clone_max_network_bandwidth 以避免把内网带宽打满。
3. 小结
本文介绍了当某个MGR节点有事务不一致时,如何找到差异的数据,以及如何进行补救。
如果担心数据不一致的话,也可以直接利用clone功能直接重建Secondary节点,也很方便。
另外,线上生产环境中,最好不要设置 slave-skip-erros,虽然遇到数据冲突、数据不存在等报错时能自动忽略跳过,但久而久之,可能数据不一致的情况越来越严重,等到某天迫不得已要切换主节点时,就压根不敢切了,那时悔之晚矣。
就这,全文完。
