我已经为 mysql 实现了基于主主复制的 HA 解决方案。前端部分有一个机制,可以保证在给定时间内只有一个数据库被读取/写入(即我们仅使用复制来实现 HA)。
我已经确认复制工作正常,但我对故障情况和恢复感到疑惑。特别是,我担心当一个主服务器发生不可恢复的故障,需要从另一个主服务器重新创建时会发生什么:
- 由于另一个主服务器处于活动状态并且很可能被使用,我无法锁定它并从中创建转储
mysqldump
(我们的数据库适度大,并且mysqldump
在使用几个月后很容易花费数小时)。 - 即使假设我有一个转储,SHOW MASTER STATUS 显示的 binlog 位置与数据库锁定后完成的转储相对应也是至关重要的。
第一个问题的简单解决方案是使用第三个数据库作为备份,我可以从中执行mysqldump
。但是,如何确保重新创建的主机能够以一致的方式从正在运行的主机开始复制?
答案1
我知道有两种基本方法可以解决此问题。首先,如果您运行的是 InnoDB 而不是 Myisam,那么您可以在事务中执行备份(--single-transaction --lock-tables=FALSE),它与 --flush-logs(不是必需的,但很好)和 --master-data 结合使用,将为您提供具有复制位置信息的一致备份。刷新日志将在创建转储之前重置日志,这意味着位置将始终为 106,而 --master-data 会将日志文件名称和位置放在转储文件中。当然,您必须在主服务器上运行此操作才能使 --master-data 正常工作。
您提到的第二种方法是使用第三台主机来创建备份。在这种情况下,您需要停止复制,确保数据库是只读的(尽管实际上,所有副本都应该是只读的,因为这不会影响复制的写入),然后创建备份并记录复制位置。在这种情况下,您不能使用 --master-data。相反,您可以这样做:
echo 'stop slave' | mysql {options)
mysqldump {your options} > DB.sql
echo 'show slave status\G' > DB.replication
echo 'start slave' | mysql {options)
如果需要从此备份恢复,则可以运行恢复,然后设置复制,其中两个参数 master_log_file 和 master_log_pos 来自 DB.replication 文件:
master_log_file = value of Master_Log_File
master_log_pos = value of Exec_Master_Log_Pos
注意:您可以并且应该从另一个副本进行测试。
附加说明:如果您有一个副本池(例如,如果您将 Web 应用程序的读取与写入分开),则副本可能会与新的主服务器不同步;如果故障转移发生在大量写入 I/O 期间,则可能会发生这种情况,因为副本异步传输,并且无法保证故障转移时备用服务器与其他副本处于同一位置。但是,这种情况还没有发生在我身上……