如果您想避免数据库中毒(即想快速恢复到某个时间点),您更喜欢哪种方法?
让我来定义数据中毒。您在数据库中插入了一些东西,这完全弄乱了内部结构和相互依赖性。我知道这意味着数据库设计可能也需要重新审视,但损害已经造成。
我想到的方法是
- 以某种方式设置复制,其中从服务器是被动的并且落后 X 小时。如果出现故障,我所要做的就是重置应用程序并将其指向作为我的新主控的从属。我怀疑这是可能的。
- 每隔几个小时对 MySQL 进行一次热备份,当检测到故障时恢复到 X 小时前的备份。这将意味着应用程序停机,因为我不能让当前应用程序继续运行。可以使用 innobackup 或 percona 进行快速备份和恢复步骤。
- 专门设计应用程序和数据库,以便新添加的数据被删除(或搁置)。这意味着我存储所有事件/状态(我想这是最困难和理论上的解决方案)
如果第一个选项可行并且它还存储所有中继日志(即 Master 上发生的任何事情都会在同一时刻传输到 Slave,但会在几个小时内自动应用)那么这将是一个完美的解决方案。也许可以在一个设置中设置多个从站以从中断和数据中毒中恢复
您可以使用 Percona Toolkit 中的 pt-slave-delay 工具让副本延迟您选择的时间量。
我通常设置一个专门用于备份的从站。这样我就可以
STOP SLAVE
,备份,和START SLAVE
。执行此方法将允许您在白天进行任意数量的备份,而无需在主服务器上停机。如果你愿意,你可以在它恢复日志后手动关闭从站。将其复制回主服务器可能会有一些停机时间,但随后您可以重播二进制日志,直到数据“中毒”为止。
您肯定需要 Master/Master 和 DBVIP 的使用
首先,让我们设置循环复制
让 db1 : Master, db2 : Slave
server-id=1
到db1:/etc/my.cnflog-bin=mysql-bin
到db1:/etc/my.cnflog-slave-updates
到db1:/etc/my.cnfskip-slave-start
到db1:/etc/my.cnfservice mysql restart
在 db1 上server-id=1
为:/etc/my.cnfserver-id=2
RESET MASTER;
在 db1 上service mysql stop
在 db1 上service mysql start
在 db2 上CHANGE MASTER TO MASTER_HOST='HostIP of db1',MASTER_PORT=3306, MASTER_USER='replusername',MASTER_PASSWORD='replpassword', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=<number>;
在 db2 上(注意:MASTER_LOG_POS 在 MySQL 5.1 之前是 98,MySQL 5.1 是 106,MySQL 5.5 是 107)service mysql start
在 db2 上START SLAVE;
在 db2 上让复制赶上来 (Seconds_Behind_Master=0)CHANGE MASTER TO MASTER_HOST='HostIP of db2',MASTER_PORT=3306, MASTER_USER='replusername',MASTER_PASSWORD='replpassword', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=<number>;
在 db1 上START SLAVE;
在 db1 上让复制赶上(Seconds_Behind_Master=0)一旦你有了循环复制,你现在可以通过在 db2 上运行来在某个时间点冻结
STOP SLAVE;
db2接下来,在 db1 上创建一个 DBVIP(示例:192.168.10.1)
使用 DBVIP 执行所有数据库读取和写入
如果您想要更新 db2,只需
START SLAVE;
在 db2 上运行并让复制赶上来。如果您想及时回到 db2 所在的位置,您可以执行那里的步骤
service mysql stop
在 db1 上rm -f mysql-bin.*
在 db1 上rm -f master.info
在 db1 上ip addr del 192.168.10.1/24 dev eth1
在 db1 上ip addr add 192.168.10.1/24 dev eth1
在 db2 上CHANGE MASTER TO MASTER_HOST='';
在 db2 上RESET MASTER
在 db2 上(Hoses 二进制日志)service mysql stop
在 db2 上service mysql start
在 db2 上service mysql start
在 db1 上如果可以通过跳过您正在同步的数据库服务器的 mysql 关闭来加快这些步骤。这只需要在数据库目标服务器上进行一些额外的清理。
这些步骤只是指南。您可能会发现我的某些步骤有点偏执。随意使用你喜欢的东西。
除了使用 Percona 的 pt-slave-delay 工具之外,另一种选择是为每个基表设置历史/审计表,它将跟踪对数据内容的所有更改,并将包含插入、更新和删除时间戳以及实际内容。您需要创建触发每个插入、更新和删除语句的触发器,然后插入到历史/审计表中。要扭转损失,您需要阅读历史/审计表并将更改应用于基表。
例如,DBIx::Class::Journal是一个从代码端自动实现这种模式的 perl 模块。如果您访问该 URL,您会看到该模块在捕获数据内容更改方面进行了相当深入的研究。日志模式包含如下表:
对于您的设置,您可能希望从每个基表都有一个历史表开始。