MySQL主从复制不能同步,查看slave状态,报错如下:
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.134
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000006
Read_Master_Log_Pos: 520
Relay_Log_File: relay-log-bin.000028
Relay_Log_Pos: 252
Relay_Master_Log_File: master-bin.000006
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1008
Last_Error: Error 'Can't drop database 'aaa'; database doesn't exist' on query. Default database: ''. Query: 'drop database aaa'
Skip_Counter: 1
Exec_Master_Log_Pos: 356
Relay_Log_Space: 868
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1008
Last_SQL_Error: Error 'Can't drop database 'aaa'; database doesn't exist' on query. Default database: ''. Query: 'drop database aaa'
1 row in set (0.00 sec)
出错原因
在两个数据库数据不一致的情况下配置了双主数据库,然后选择将脏数据删掉,在清理脏数据的时候没有暂停二进制日志,删除的行为被记录在二进制日志中,而在令外的数据库中并没有脏数据,所以在同步删除时会执行失败,导致中继日志停止运行。
解决方法
1、如果使用的是手动设置的二进制日志的位置
mysql> stop slave;
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; #将同步指针向下移动一个,可以重复操作
mysql> START SLAVE;
2、如果使用的是gtid自动协商二进制日志位置的方式
mysql> stop slave;
mysql> set global gtid_mode=ON_PERMISSIVE; #允许更改二进制日志的位置
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; #将同步指针向下移动一个,可以重复操作
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G;
### Once caught up set it back
mysql> set global gtid_mode=ON; #配置成功之后恢复原先的配置
如果不先允许更改二进制的位置,出现如下报错
ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction
避免出错的方法
在清理脏数据时先将二进制日志停掉:set sql_log_bin=0;
临时停止,只在当前sql会话中生效,在操作完成之后记得将二进制日志打开:set sql_log_bin=1;
或者直接退出当前sql会话重新打开。
在备份或者恢复数据库时同样建议使用此操作。