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 ""
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律