MySQL/MariaDB复制架构中,如何确认副本处于一致状态以保障后处理操作正常执行?
MySQL/MariaDB复制架构中,如何确认副本处于一致状态以保障后处理操作正常执行?
针对你描述的场景——主库每分钟有15秒的非一致性更新,副本需要在同步到主库的一致状态后执行后处理操作,我整理了几个适配MariaDB 10.3+版本的实用方案:
一、利用GTID(全局事务标识符)做一致性同步校验
如果你的主从集群已经开启了GTID(这是10.3+版本推荐的配置),这个方法最省心:
- 主库端:每次更新流程全部完成后,记录下最后一个事务的GTID。你可以通过执行
SHOW MASTER STATUS;查看Executed_Gtid_Set,或者在更新脚本的末尾直接获取当前GTID(比如用SELECT @@GLOBAL.GTID_EXECUTED;),把这个值存入主库的一个专用表(比如CREATE TABLE sync_checkpoints (id INT AUTO_INCREMENT PRIMARY KEY, gtid_set TEXT, create_time DATETIME DEFAULT NOW());)。 - 副本端:在需要执行后处理前,先从主库的
sync_checkpoints表读取最新的GTID集合,然后执行SELECT WAIT_FOR_EXECUTED_GTID_SET('这里填读取到的GTID集合');。这个语句会自动阻塞,直到副本完全执行完这个GTID集合对应的所有事务——也就意味着副本已经同步到主库更新完成后的一致状态了。之后你就可以放心启动后处理操作。
二、手动标记一致性检查点
如果暂时不想用GTID,也可以用简单的表标记法:
- 主库端:在每次更新流程全部完成后,往主库的一个专用标记表插入一条记录,比如:
(先提前创建这个表:INSERT INTO replication_consistent_marks (mark_time, status) VALUES (NOW(), 'ready');CREATE TABLE replication_consistent_marks (id INT AUTO_INCREMENT PRIMARY KEY, mark_time DATETIME, status VARCHAR(20));) - 副本端:写一个脚本轮询这个表,当查到最新的
ready标记时,说明副本已经同步到主库的一致状态。此时可以先把这条标记记录标记为processing,再启动后处理;处理完成后可以删除或归档这条记录,避免重复触发。
三、基于二进制日志位置的精准同步
这个方法适合对复制细节把控要求高的场景:
- 主库端:更新流程完成后,执行
SHOW MASTER STATUS;,记录下File(二进制日志文件名)和Position(日志偏移量)这两个值,同样存入主库的专用表中。 - 副本端:执行
STOP SLAVE;,然后运行:
这条命令会让副本只同步到指定的binlog位置就停止,此时副本就处于主库更新完成后的一致状态。之后你可以执行后处理,完成后再执行START SLAVE UNTIL MASTER_LOG_FILE='主库的binlog文件名', MASTER_LOG_POS=主库的偏移量;START SLAVE;恢复正常复制。
额外注意事项
- 如果你的后处理需要写回主库,一定要做好复制过滤配置(比如通过
replicate_ignore_db或者GTID的事务来源过滤),避免出现循环复制的问题。 - 主库的更新流程尽量用事务包裹,如果是多个事务,一定要确保标记操作是在所有更新事务提交后执行,否则标记的一致性点会不准确。
备注:内容来源于stack exchange,提问作者GingkoFr




