MySQL主从不一致解决办法

先查看mysql错误日志,定位同步失败原因。如果错误可以忽略,则可以执行以下步骤忽略错误,重新开启同步。

没有开启GTID

#先停止主从同步
stop slave;
#设置忽略数量
set global sql_slave_skip_counter = 1;
#重新开启主从同步 start slave;

开启GTID

#停止主从同步
stop slave;
#错误的事务GTID,错误日志里可以找到
set gtid_next='bb22e27a-67d6-11ee-bbaa-005056bd2448:3';
#添加空事务跳过出错的事务
begin;commit;
#查看是否设置成功
select @@gtid_next
#改回自动
set gtid_next='automatic';
#重新开启主从同步
start slave;

如果错误涉及到插入数据,则可以在错误日志中找到出错的事务binlog日志位置。提取插入语句,手动在从库上执行。

根据指定节点导出数据
mysqlbinlog --start-position='1839' --stop-position='3150' /data/mysql/mysql8.0.33/data/mysql-bin.000007 > /data/bak.sql

还有一种就是发现较晚,数据差异较大。则需要恢复从库数据,再重新开启主从同步。

主要步骤: 导出主库数据,恢复到从库,重新开启主从同步。

 1. 先停止从库

从库上执行 stop slave;

 2  在从库mysql bin目录下导出主库数据

./mysqldump -h192.168.174.201 --port=3359 -uroot -p'pwd' --default-character-set=UTF8MB4 --single-transaction --events --triggers --routines --master-data=2 --all-databases > /data/bak.sql

-h192.168.174.201  指定主库的服务器地址(也可以不加这个参数,在主库上导出数据再scp到从库服务器)

--port=3359   数据库端口

--default-character-set 指定导出字符集

--single-transaction  开启单个事务,导出过程不加锁。确保导出的数据就是截止到执行导出命令的时间点。此选项会将隔离级别设置为:REPEATABLE READ。需没有下列语句ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE,因为一致性读不能隔离上述语句。所以如果在dump过程中,使用上述语句,可能会导致dump出来的文件数据不一致或者不可用

--events --triggers --routines   导出所有的事件, 触发器,存储过程

--master-data=1   2以注释的形式写出导出时间点的binlog名字及位置。1不注释,恢复数据的时候会直接执行

--all-databases    导出所有库, 如果单个库直接最后面写库名字,如果是某个表在库名后面写表名, 如果是多个库则--databases后面写多个库,空格隔开

--set-gtid-purged=off   再介绍下这个参数,开启GTID时有用。如果是on会设置导出的数据库GTID和主库一致,导入的数据不会改变binlog。如果不是全库导出设成off,因为会导出所有GTID。如果导出的数据库有可能作为主库则必须设成off, 因为on不生成binlog, 从库无法同步导入的数据。如果作为从库恢复数据,建议设成on,off导入的数据会重新生成一套GTID。

 3.  恢复从库数据,mysql bin目录下执行

mysql -uroot -p'pwd' < /data/bak.sql

如果是恢复到某个库就在后面加上库名   mysql -uroot -p'pwd' databasenamexxx < /data/bak.sql

4.  重新开启主从同步

如果导出时--master-data=1则直接开启主从同步即可, start slave;

如果导出时--master-data=2则head -n 100 bak.sql   查看前几行有binlog文件名和位置。在从库上执行如下步骤

reset slave all;  //重置从库binlog等信息

change master to master_host='192.168.174.210', master_port=3306, master_user='root',master_password='bwt4567', master_log_file='mysql-bin.000006',master_log_pos=157; //指定主从同步

change master to master_host = '192.168.174.210', master_port = 3306, master_user = 'root',master_password='bwt4567',master_auto_position = 1; //如果开启GTID,则更简单,不需要指定binlog同步位置

start slave;

查看从库状态, 如果这俩个线程运行状态都是yes, 则代表主从启动成功。

show slave status;

 

备库是个良好的习惯哦,下面附赠linux shell脚本,

1. crobtab -e  编辑linux定时任务脚本,每天凌晨俩点执行备库任务。

0 2 * * * /bin/bash /data/bak_sql/bakdb.sh

2. 创建bakdb.sh,指定备库文件目录和文件名。

MYSQL_BACKUP_DIR=/data/enterprise_bak_sql
BK_NAME=`date +%Y%m%d_%H%M%S`bak.sql
echo `date +%Y/%m/%d_%H:%M:%S`" :  mysql dump starting!"
if [ `ps -ef|grep -w mysqld|grep -v "grep"|wc -l` == 1 ];then
 mysqldump -u root -p'bwt4567'  --set-gtid-purged=off --default-character-set=UTF8MB4 --single-transaction --events --triggers --routines --all-databases --source-data=2 >${MYSQL_BACKUP_DIR}/${BK_NAME}
 IS_SUCCEED=`tail -n 5 ${MYSQL_BACKUP_DIR}/${BK_NAME} | grep -w "Dump completed" | wc -l`
 if [ $IS_SUCCEED -gt 0 ];then
  gzip ${MYSQL_BACKUP_DIR}/${BK_NAME}
  if [ $? == 0 ];then
   find ${MYSQL_BACKUP_DIR} -name "*.gz" -type f -mtime +2 -exec rm {} \;
   echo `date +%Y/%m/%d_%H:%M:%S`" : [NOTE]: mysql dump succeed and gzip succeed!"
  else
   echo `date +%Y/%m/%d_%H:%M:%S`" : [WARRING]: gzip failed!!!"
  fi
 else
  echo `date +%Y/%m/%d_%H:%M:%S`" : [ERROR]: mysql dump failed!!!"
 fi
else
 echo `date +%Y/%m/%d_%H:%M:%S`" : [ERROR]: database not startup!"
fi
echo "======================================="
echo ""
posted on 2023-08-29 14:21  lvguoliang(学无止境)  阅读(442)  评论(0编辑  收藏  举报