问题场景
MySQL主从同步失效,slave因为各种原因跟丢了master的数据写入,无法继续正常进行后续数据同步。
解决思路
重置主从同步关系,让slave从当前mster最新数据进行同步,其核心就是两点:
- 将master的最新数据导入slave
- 让slave访问到导入数据所对应的binlog和binlog position
解决步骤
网上大多数步骤都要求停业务,停业务的目的是能备份到最新的主节点的数据以及这份数据对应的同步状态,否则会同步失败,因为当你重置master再导出主节点数据之间,主节点是可能继续写入数据的,这样会导致你不知道应该从binlog的哪个position进行主从同步。折腾了一下午以后,找到了不用停业务也能准确备份数据和当前数据所在binlog position的方法。
At Slave Server:
停止slave:
mysql> STOP SLAVE;
At Master Server:
停止master:
mysql> RESET MASTER;
mysql> FLUSH TABLES WITH READ LOCK;
导出主节点数据:
root@mysql-0:/# mysqldump -u root -p --add-drop-table --routines --events --all-databases --force --master-data > all-databases.sql
这里有几个关键的参数:
--add-drop-table:在create table语句前会加上drop table语句,这样导入时就不用手动去清理slave的数据了
--all-databases:包含所有的database,就不用一个数据库一个数据库的备份了
--master-data:这个对主从同步是比较重要的参数,加了之后mysqldump会自动记录当前mysqldump时的binlog position
At Slave Server:
导入备份出来的数据:
root@mysql-1:/# mysql -uroot -p < all-databases.sql
导入之后,网上找到的大部分资料都让执行reset slave和CHANGE MASTER TO MASTER_LOG_FILE='mysql-0-bin.000001', MASTER_LOG_POS=1,目的是让slave去跟master重置后的起始节点,但实际上对于我们没有停业务的系统来说,这样做是不现实的,因为binlog pos不会是1,所以我们在前面导出的时候加了--master-data就起作用了,里面就包含change master to语句,刚才导入的时候就已经带上了,就不用单独去执行了。所以接下来直接启动slave就好:
mysql> START SLAVE;
然后通过这个命令查看SLAVE状态,如果Slave_IO_Running和Slave_SQL_Running都是yes的话则重置成功:
mysql> show slave status \G