如何恢复MySQL主从数据一致性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何恢复MySQL主从数据一致性相关的知识,希望对你有一定的参考价值。

1. 备份主库数据,并在从库上恢复,在历史数据一致性的基础上开启同步,但这种方法比较麻烦,必须在主库上执行锁表操作,阻止客户端对于表数据的更新操作,而且在数据量大的情况下,备份也是个耗时的工程。其实,这种方法在实际生产环境中也很少用。
2. Skip掉相关错误
其实,这个说活不是很严谨,准备的说,是跳过相关的事务。在我今天这种情况下,就是skip掉因违反主键约束而失败的insert语句。
参考技术A XtraBackup 在 mysql 备份场景中被广泛使用,大家一定不陌生。我们也在之前的两篇文章中分享了其备份的原理。(详见 [原理解析] XtraBackup全量备份还原 & [原理解析] XtraBackup增量备份还原)本文想要描述的是 XtraBackup 恢复时参数 apply-log-only 的作用,不知道大家有没有注意到,这个参数如果不设置,可能会产生数据不一致的惨剧。
使用 XtraBackup 对数据库做备份,实际上就是拷贝 MySQL 的数据文件,为了保证备份数据的最终一致,也会同时拷贝备份过程中的 Redo log。

MySQL主从数据不一致,需要重新关联

情况是这样的:目前的库是一主两从,大部分的修改和读操作都是在主库上完成的,两个从库基本只做热备之用。前段时间由于重启主库,所以业务人员临时启用了其中一台从库做为主库,并对从库进行了写入操作。后来主库重启好后,他们又让原来的主库恢复了主库的职能,之前暂时做从的数据库就断开了与主库的主从关系。现在他们需要我把断开的从库跟主库重新关联上,并表示一切的数据都以原来的主库为准,所以可以把从库上的东西都删掉,然后导入主库的数据。

目前有几个问题,一个是需要整个导出的库很大,光表数据大小就有61G,数据库目录的大小有100多G,其中ibdata1文件就占了85G;
第二个是数据库里的表只有一张用的是MYISAM引擎,其他都用的是INNODB引擎,所以不能使用xtrabackup工具来导出。

然后我想到了四种方案:
一是使用Innobackupex+binlog日志还原从库数据;
二是使用mysqldump+binlong日志来还原从库;
三是直接拷贝从库上的数据然后scp到需要重新关联的从库;
四是使用percona-toolkit工具来重构数据,使主从数据库数据一致。

我是倾向于mysqldump+binlong,但是本身数据库就很大,估计光导出就要很久了。。。
然后我又看网上说用Innobackupex导出大数据更快,但是毕竟要在正式环境上安装工具,怕对现网环境造成影响
第三种方案需要期间停止所有从库,然后转移数据,这对空间和时间都有很大的要求,恐怕不容易满足。。。而且不知道把从库都先停止了会不会让原本没有问题的从库出现新问题
第四种方案貌似需要在主库上进行操作,而且会重构主库上的数据,我觉得风险更大。。。所以正在纠结中,不知道该怎么办

不知各位有何意见,或者有什么新的方案能够一起分享下呢?

参考技术A 1. 在有主键或者唯一键的情况下,Slave 重放 Binlog 并不会去比较检索到的记录的每一列是否和BI相同,因此如果 Slave 和 Master 存在数据不一致,会直接覆盖 Slave 的数据而不会报错。
2. 在没有主键或者唯一键的情况下,Hash Scan / Hash Scan Over Index 的执行效率 在理论上分析高于 Table Scan 和Index Scan 。
3. 在没有主键或者唯一键的情况下,Slave 选择的二级索引是第一个所有的列都在 BI 中存在的索引,不一定是 Master 执行计划所选择的索引。
参考技术B 直接拷贝物理文件备份,但是这种方式会产生问题,INNODB引擎无法物理备份,需要修改后备份。不妨做个修改,以后的维护一劳永逸。数据库主从备份可能会产生一些问题,也就是数据不可逆,最好做成主主备份,尤其是web和后台数据库同时多用户使用的情况下。

master1上的my.cnf添加:
[mysqld]
# for repl
log-bin=mysql-bin
server-id=1
binlog-do-db=TestXXX
binlog-ignore-db=mysql
replicate-do-db=TestXXX
replicate-ignore-db=mysql
log-slave-updates
slave-skip-errors=all
auto_increment_increment=2# 应设为整个结构中服务器的总数
auto_increment_offset=1# 设定数据库中自动增长的起点,避免两台服务器数据同步时出现主键冲突
master2上的my.cnf添加:
[mysqld]
# for repl
log-bin=mysql-bin
server-id=2
binlog-do-db=TestXXX
binlog-ignore-db=mysql
replicate-do-db=TestXXX
replicate-ignore-db=mysql
log-slave-updates
slave-skip-errors=all
auto_increment_increment=2
auto_increment_offset=2
重启两台机器上的服务
master1上指定master2为主:
CHANGE MASTER TO MASTER_HOST='master2',MASTER_USER='username',MASTER_PASSWORD='passwd';
START SLAVE;
master2上指定master1为主:
CHANGE MASTER TO MASTER_HOST='master1',MASTER_USER='username',MASTER_PASSWORD='passwd';
START SLAVE;本回答被提问者和网友采纳

以上是关于如何恢复MySQL主从数据一致性的主要内容,如果未能解决你的问题,请参考以下文章

MySQL主从数据不一致,需要重新关联

mysql------针对主从同步的情况两个库进行数据校对及恢复

如何保证主从复制数据一致性

如何利用percona-toolkit工具检查MySQL数据库主从一致性以及修复

MySQL GTID 主从复制

FAQ系列 | 如何保证主从复制数据一致性(转)