记一次 MySQL 主从数据不一致

项目的 Mysql 数据库前期设置为主从,主写从读。一段时间后,出现主从数据不一致的问题。本文记录了问题排查和解决方案。

登录从库查看问题,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> show slave statue \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Log_File: mysql-bin.000008
Read_Master_Log_Pos: 790812108
Relay_Log_File: mysqld-relay-bin.000016
Relay_Log_Pos: 509613377
Relay_Master_Log_File: mysql-bin.000005
......
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 509613231
Relay_Log_Space: 4012063490
......
Seconds_Behind_Master: 74225
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:

Last_Errno 可以查看到,1062 duplicate key 的错误,简单的解决方案,
执行下面命令跳过错误的事务:

1
mysql> stop slave;SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;start slave;

执行完成后,可以再次查看从库状态,

1
2
3
mysql> show slave statue \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

但上面的方法只能跳过下一条事务,但不能确认具体事务,这时可以登录主库,运行

1
mysql> SHOW BINLOG EVENTS in 'mysql-bin.000005' from 509613231 limit 10;

查看接下来的部分 sql,来选择需要跳过的事务数。

对于一些常见的错误类型,比如 1062(duplicate entry),1032(主从数据不一致),1054(unknown column), 可以考虑忽略这些类型的错误, 这时,可以设置 slave-skip-errors
修改从库的 my.cnf,增加

1
slave-skip-errors=1062,1032

重启从库后,这些类型的错误就会被忽略。

出现上述的问题,一个原因是master有写的进程被KILL了,但写操作没执行完毕但是已经写入到了BINLOG。
PS: 以上方法只对 mysqld_safe 测试。