mysql主从复制报错及解决方法

446 阅读9分钟

mysql主从复制报错及解决方法

查看主从同步状态:

-- 从库执行
show slave status\G

查看主从报错binlog:

-- 从库执行
select * from performance_schema.replication_applier_status_by_worker\G

1. mysql数据库slave同步报错 1366:

原因:数据库表的字符集和表中的字段的字符集不一致导致的

解决方法:依据实际情况改成一致的

2. mysql数据库slave同步报错 1061:

原因:主库上某表的索引已经在slave对应表上存在,主库继续同步到slave上,会提示slave上某表索引已经存在而导致同步报错。

解决方法:在从库操作删除表索引

3. mysql主从复制报错 1060

原因:slave上表字段重复

解决方法:删除报错指出的重复字段

4. mysql同步报错 1396

原因:主库删除从库上不存在的数据库用户导致的

解决办法:

mysql>stop slave;
mysql>  set global sql_slave_skip_counter=1
mysql>start slave;

5. mysql主从复制报错 1007

slave 上报错:

Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can'create database 'wjw02'; database exists' on query. Default database: 'wjw02'.Query: 'create database wjw02'
Replicate_Ignore_Server_Ids:

原因:slave上早已经存在master上同名的的库,所以master上再次创建库,slave上会提示库已经存在,导致报错;

解决办法:

mysql>stop slave;
Query OK,0 rows affected (0.01 sec)

mysql>set global sql_slave_skip_counter=1;
Query OK,0 rows affected (0.00 sec)

mysql>start slave;
Query OK,0 rows affected (0.01 sec)

或者修改配置文件跳过1007错误

6. mysql主从复制报错 1008

slave上提示:

Last_SQL_Errno:1008
              Last_SQL_Error: Error 'Can't drop database 'wjw02'; database doesn't exist' on query. Default database:'wjw02'. Query: 'drop database wjw02'

原因:从库提前删除数据库wjw02,然后在master上再次删除wjw02库,slave上提示为wjw02库不存在,导致复制报错;

解决方法:

在slave上执行:

mysql>stop slave;
Query OK,0 rows affected (0.02 sec)
mysql>set global sql_slave_skip_counter=1; 
Query OK,0 rows affected (0.05 sec)
mysql>start slave;
Query OK,0 rows affected (0.02 sec)

7. 将slave_skip_errors=参数写入配置文件

将slave_skip_errors=参数写入slave上的配置文件my.cnf

[root@localhost ~]# grep slave_skip_errors /etc/my.cnf

slave_skip_errors=1007,1008

[root@localhost ~]# /etc/init.d/mysqld restart

这样可以直接忽略slave同步报错信息

注意:生产环境考虑到主从库数据的一致性,是不允许不分情况的set global sql_slave_skip_counter=1; slave_skip_errors 操作这样的参数来忽略错误的,如果遇到主从同步失败的话,就让他卡到那了,人工介入进行手动恢复故障

8. slave_exec_mode 参数可以动态自动处理同步复制错误

注意:此参数的设置只能忽略错误1032和1062的错误。

mysql>show variables like 'slave_exec_mode';
+-----------------+--------+
|Variable_name   | Value  |
+-----------------+--------+
|slave_exec_mode | STRICT |
+-----------------+--------+

此参数默认是STRICT严格模式;

将该参数设置为IDEMPOTENT模式,slave同步出现1032错误(记录没找到)和1062错误(主键重复),就会自动跳过次错误,并且记录到错误日志里面,其实此参数和slave_skip_errors作用是一样的。

只不过slave_skip_errors参数必须写入配置文件my.cnf,重启mysql,然而IDEMPOTENT默认不需要重新启动slave的mysql服务。

mysql>set global slave_exec_mode='IDEMPOTENT';
Query OK,0 rows affected (0.05 sec)
mysql>show variables like 'slave_exec_mode';
+-----------------+------------+
|Variable_name   | Value      |
+-----------------+------------+
|slave_exec_mode | IDEMPOTENT |
+-----------------+------------+
1 row inset (0.00 sec)
mysql>stop slave;
Query OK,0 rows affected (0.00 sec)
mysql>start slave;

演示:

slave上操作:

mysql>select * from dr_user_info;
+----+----------------------------------+-------------+------------+--------+
| id |dev_id                           |tel         | updatetime | pwd    |
+----+----------------------------------+-------------+------------+--------+
| 20 |CFD0CCDA603705F35C8EE74427C9CC45 | 13713340729 | 1488174916 | 111111 |
| 21 |11713EA0EDAFC1113E9AB016471BBDCF | 18341732393 | 1487632768 | 111111 |
| 22 |C9DEBE883FF6C05A19D5C0487E9C9D63 | 18600271207 | 1488521317 | 111111 |
| 23 |D73C9DADAB3611D82B7D5CA11B62DBA1 | 18974748447 | 1491177725 | 111111 |
| 24 |qwertyuiop                       |18234123308 | 1491177726 | 666666 |
+----+----------------------------------+-------------+------------+--------+
5 rows inset (0.00 sec)
mysql>delete from dr_user_info where id=24;

在master上操作:

mysql>select * from dr_user_info;
+----+----------------------------------+-------------+------------+----------+
| id |dev_id                           | tel         | updatetime | pwd      |
+----+----------------------------------+-------------+------------+----------+
| 20 |CFD0CCDA603705F35C8EE74427C9CC45 | 13713340729 | 1488174916 | 111111   |
| 21 |11713EA0EDAFC1113E9AB016471BBDCF | 18341732393 | 1487632768 | 111111   |
| 22 |C9DEBE883FF6C05A19D5C0487E9C9D63 | 18600271207 | 1488521317 | 111111   |
| 23 |D73C9DADAB3611D82B7D5CA11B62DBA1 | 18974748447 | 1491177725 | 111111   |
| 24 |qwertyuiop                       |18234123308 | 1491177726 | 33333333 |
+----+----------------------------------+-------------+------------+----------+
5 rows inset (0.00 sec)

mysql>select * from dr_user_info;
+----+----------------------------------+-------------+------------+--------+
| id | dev_id                           | tel         | updatetime | pwd    |
+----+----------------------------------+-------------+------------+--------+
| 20 |CFD0CCDA603705F35C8EE74427C9CC45 | 13713340729 | 1488174916 | 111111 |
| 21 |11713EA0EDAFC1113E9AB016471BBDCF | 18341732393 | 1487632768 | 111111 |
| 22 |C9DEBE883FF6C05A19D5C0487E9C9D63 | 18600271207 | 1488521317 | 111111 |
| 23 |D73C9DADAB3611D82B7D5CA11B62DBA1 | 18974748447 | 1491177725 | 111111 |
+----+---------
​
​
​
mysql> show slave status\G

查看错误日志

[root@localhost logs]# tail -1/data/mysql/logs/mysql-error.log 2017-05-1405:22:55 4707 [Warning] Slave SQL: Could not execute Delete_rows event on tabledr_brower_db.dr_user_info; Can't find record in 'dr_user_info', Error_code:1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master logmysql-bin.000010, end_log_pos 5298692, Error_code: 1032

9. mysql同步报错1062(主键重复)

原因:slave上表记录重复,导致slave复制报错1062主键重复

在slave上擦看报错:

Last_SQL_Errno:1062
              Last_SQL_Error: Could notexecute Write_rows event on tabledr_brower_db.dr_user_info; Duplicate entry '24' for key 'PRIMARY', Error_code:1062;handler error HA_ERR_FOUND_DUPP_KEY; the event's master logmysql-bin.000010, end_log_pos 5295916

解决办法:删除slave上表dr_user_info重复的id为24的记录

mysql>delete from dr_user_info where id=24;
mysql>stop slave;
Query OK,0 rows affected (0.01 sec)
mysql>start slave;
mysql>show slave status\G

在master上更新一条表记录然而在slave上找不到这条记录报错 1032

在slave上擦看报错:

Last_SQL_Errno:1032
              Last_SQL_Error: Could notexecute Delete_rows event on tabledr_brower_db.dr_user_info; Can't find recordin 'dr_user_info', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; theevent's master log mysql-bin.000010,end_log_pos 5296175

解决办法:

在master上查看mysql-bin.000010日志上的sql语句,分析出错处5296175,sql语句在干嘛,依据情况处理改事务

注意:如果是执行的update语句,此时slave同步报错1032的话,是不允许set global sql_slave_skip_counter=1;进行忽略这个错误的,建议查看binlog日志看下是卡在什么地方,然后在slave库上把这条不存在的记录insert,然后在start slave开启同步;

slave的中继日志relay-log损坏导致mysql同步报错

原因:当slave意外宕机时,有可能会损坏中继日志relay-log,再次开启同步复制时,报错信息如下;

解决办法:找到同步的binlog日志和pos点。然后重新同步,

提示:在mysql5.5版本及以上版本,已经考虑到slave宕机导致relay-log损坏的问题造成mysql同步失败。

即在slave的my.cnf配置文件中加入参数relay_log_recovery=1,就可以了

mysql主从复制报错:2003

在slave上擦看报错:

Last_IO_Errno:2003
              Last_IO_Error: error connectingto master 'rep@10.0.0.201:3306' - retry-time60 retries: 2

原因有多种,可能是slave上防火墙开启限制了3306端口,也可能是在slave上执行change master to 时,指定的连接复制数据库的账户和密码不对导致的。也可能是对端的master开启防火墙做了3306端口的的限制等,也有可能是服务器之间网络的问题导致的

还有就是master上的my.cnf配置文件使用参数:binlog_ignore_db=mydb1,slave上的my.cn配置文件使用参数:replicate-ignore-db =mydb1,也可以导致mysql同步报错2003

master上:

[root@localhost~]*# grep wjw01 /etc/my.cnf*   binlog_ignore_db= wjw01 
​
[root@localhost~]*# /etc/init.d/mysqld restart*

slave上:

[root@localhost~]# tail -3 /data/mysql/logs/mysql-error.log 2017-05-1415:59:54 5335 [Warning] Storing MySQL user name or password information inthemaster info repository is not secure and is therefore not recommended. Pleaseconsider using the USER and PASSWORD connection options for START SLAVE; seethe 'START SLAVE Syntax' in the MySQL Manual for more information.
2017-05-1415:59:54 5335 [ERROR] Slave I/O: error reconnecting tomaster'rep@10.0.0.201:3306' - retry-time: 60 retries: 1, Error_code: 2003
2017-05-1416:00:54 5335 [Note] Slave: connected tomaster'rep@10.0.0.201:3306',replication resumed in log 'mysql-bin.000014' atposition628

binlog_ignore_db引起的同步复制故障

一个网友的案例:

在mysql的master上采用binlog_ignore_db命令忽略了一个库以后,使用mysql –e 执行的所有的语句就不写入binlog了,原因是在进行主从复制时,有一个库不复制,查看了一下他的配置,binlog格式为row模式,跟他要了当时的sql语句:

mysql -e ‘create table db.tb like db.tb1’;

查看mysql的手册知道忽略某个数据库的复制有两个参数,一个是binlog_ignore_db,另一个是replicate-ignore-db,他们是有区别的:

binlog_ignore_db参数是设置在master上的,例如:binlog_ignore_db=test,那么针对test库下的所有的操作(增删改)都不会记录下来,这样slave上接受主库上的binlog时文件量就会减少,这样做好处是可以减少网络io,减少slave端I/O线程的I/O量,从而最大程度的优化复制性能,。但是也存在一个隐患,在下面会提到。

replicate-ignore-db是设置在slave上的replicate-ignore-db=test1,那么针对test1库下的所有的操作(增删改)都不会被sql线程执行,

结论:如果想在slave上忽略一个库的复制,最好不要采用binlog_ignore_db这个参数,使用replicate-ignore-db= db来代替