MySQL Slave复制失败:如何识别导致失败的SQL

MySQL Slave replication failure: How to identify SQL which is causing it to fail

我在AWS RDS上运行MySQL。由于以下错误,从属复制被卡住。 它说它无法在从属服务器表中找到一条记录...是否有办法知道哪个记录? 或失败的SQL!

Read Replica Replication Error - SQLError: 1032, reason: Could not
execute Update_rows_v1 event on table customers.visitor; Cant
find record in visitor, Error_code: 1032; handler error
HA_ERR_END_OF_FILE; the events master log
mysql-bin-changelog.206572, end_log_pos 12627388


使用mysqlbinlog读取日志。

1
2
mysqlbinlog --verbose --base64-output=decode-rows mysql-bin-changelog.206572 \\
| awk '/end_log_pos/{flag=0}/end_log_pos\\ 12627388\\ /{flag=1}flag'

从错误消息中,这看起来像是一个以行格式记录的事件,因此mysqlbinlog会将其解码为伪sql,显示每一列及其顺序位置,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
### UPDATE `my_db_name`.`my_table_name`
### WHERE
###   @1=70
###   @2=1476602910
###   @3=NULL
###   @4=NULL
###   @5=NULL
###   @6=NULL
###   @7=NULL
### SET
###   @1=70
###   @2=1476602910
###   @3=1476602926
###   @4=000000016.283000000
###   @5=NULL
###   @6='0'
###   @7=NULL

输出中的@1@2等是第1列,第2列等。binlog不包含这些列的实际名称,因为假定它们在主服务器和从属服务器上是相同的,并且它们因此是多余的...因此mysqlbinlog创建此伪sql来说明它如何解释记录的更改事件。 WHERE是更新前在主服务器上显示的行的版本(这将是在从属服务器上找不到的行),而SET是更新后的行的值主服务器(从服务器应将行更改为看起来像是什么,如果已存在)。

这不会识别您的原始查询,但是会向您显示在主服务器上存在但在从属服务器上丢失的实际行。

如果还没有日志,则可以首先从主数据库中获取日志:

1
2
3
mysqlbinlog --host=xxxx.rds.aws-regi-on.amazonaws.com --user 'rds-master-user' \\
--password='rds-master-password' --read-from-remote-server \\
--raw mysql-bin-changelog.206572

必须从主服务器获取日志。在这种情况下,无法从从站获取它。 (如果不是RDS,则可以通过SSH登录到Shell来连接到从属服务器,然后直接读取中继日志,但是这些文件无法从外部访问,这就是为什么您必须去主服务器获取日志的原因,在RDS中。)

除非您已经将RDS配置为将Binlog保留的时间长于技术上所需的时间,否则该日志可能不再在主数据库上可用,因此您可能会不走运直到下次。您可以使用MySQL 5.6和更高版本的所有RDS实例上包含的自定义过程在RDS上配置binlog保留。要将日志保留时间设置为24小时,例如:

1
CALL mysql.rds_set_configuration('binlog retention hours', 24);

另请参阅http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html

感谢使用awk在两个模式之间找到线的灵感来源。

请注意,上面的命令匹配并打印出发生错误的事件后,由于awk继续扫描到文件末尾,它似乎挂起了。 Control-C终止。