我有以下 Mysql 复制架构:
A(主)->B(从/主)->C(从)
如果复制由于某种原因被破坏(A->B),我可以复制A的binlog,找到B最后执行的语句对应的位置并重播它。 所有复制链中 bin/中继日志中事务/语句的顺序是否相同? (复制使用一个线程,因此可能是相同的顺序。)
更新:我应该这样问:“在所有复制链中,二进制日志中的语句/事务的顺序是否相同?我们可以在任何主机上重播任何日志并将任何从站(c)重新指向主站(A)” 看来答案是:“是”。但官方确认或文档(源代码)链接尚未发布。
UPDATE2:从官方文档到innodb_support_xa:
启用 InnoDB 对 XA 事务中两阶段提交的支持,从而导致事务准备时需要额外的磁盘刷新。 XA 机制在内部使用,对于任何打开二进制日志并从多个线程接受数据更改的服务器来说都是必不可少的。如果禁用 innodb_support_xa,事务可以按照与实时数据库提交事务不同的顺序写入二进制日志,这在灾难恢复中或在复制从站上重播二进制日志时可能会产生不同的数据。
直接回答你的问题,不。
您的拓扑:
(a) 主服务器 -> (b) 副本 -> (c) 副本
如果您希望管理复制拓扑、移动从属设备和故障转移,您应该考虑使用以下其中一种:
您应该找出
MySQL 复制如何不同步的根本原因并修复该问题以防止出现此问题,这毫无意义。
在您的示例中,A 和 B 都正在写入 binlog。这些日志中的语句顺序将是相同的,尽管我找不到文档来证明这一点,但这是复制的基本原则。如果顺序不同,那么数据可能很容易不同步。你是对的,复制从线程是单线程的,因此主机 B 将按顺序读取和写入语句。
但是,如果某些数据直接写入主机“B”,那么根据写入的内容,B 和 C 的数据当然会与“A”不同。
在进行更改之前,请确保您已备份服务器。在 B 和 C 上运行“SHOW SLAVE STATUS”并将输出复制/粘贴到某处作为参考。
要使“C”从“A”复制,您需要在“A”的二进制日志上找到与“C”当前查看“B”的位置相对应的位置。有几种方法可以做到这一点,包括使用 mysqlbinlog 工具手动查找查询并从该点开始。
更快的方法是让‘C’100%追上‘B’。假设“B”上的复制已停止。在 B 上使用“SHOW SLAVE STATUS”来获取在“C”上运行以下查询的参数。
CHANGE MASTER TO MASTER_HOST = '[Master_Host]', MASTER_LOG_FILE='[Master_Log_File]', '[Exec_Master_Log_Pos]';
您可能需要添加其他选项:
MASTER_USER='__USER__', MASTER_PASS='__PASS__',
这将告诉主机“C”从“B”所在的位置继续进行复制。如果您像一个优秀的 dbadmin 一样偏执,那么您将使用 mysqlbinlog 检查主机“A”上的二进制日志,并确认“C”新位置处的查询/时间戳,并将该点附近的查询与“C”上的数据进行比较确认这是重新启动复制的点。比如:
mysqlbinlog --read-from-remote-server --host=HostA --user.. --password=.. --start-position=[Exec_Master_Log_Pos - 100] --stop-position=[Exec_Master_Log_Pos + 100] Master_Log_File
关于 mysqlbinlog 的好消息是,它还可以让您从另一台服务器读取 binlog 的副本,并将其转换为可以在本地重播的 SQL 语句。这在灾难恢复场景中非常有用。
如果由于任何特定原因您不想使用从站 B,并且您确定在从站 B 复制中断之前,B 中的所有数据已复制到 C,并且您知道复制中断的指针,那么您可以执行 binlogs直接在从属 C 上,现在您可以使从属 C 成为主 A 而不是 B 的从属。
如果问题有所不同,请详细说明。