对因缺少记录而导致的复制失败进行故障排除
使用带二进制日志复制功能的 Amazon RDS for MySQL 或 MariaDB 时,您可能会遇到由于只读副本上缺少记录导致进程停止的复制故障。此部分介绍如何诊断和解决此问题。
常见原因
源和副本之间的数据不一致可能是由于下列情况之一所导致:
-
在副本上手动修改数据
-
使用
sql_replica_skip_counter(在 MySQL 8.0.26 之前为sql_slave_skip_counter)跳过了事务 -
使用迁移工具进行初始数据同步期间,副本上缺少行
识别问题
此问题的一个常见指标是 Error 1032(附带消息 Can't find record)。副本的错误日志中显示以下错误消息:
2025-11-04T21:24:11.038899Z 566 [ERROR] [MY-010584] [Repl] Replica SQL for channel '': Worker 1 failed executing transaction 'ANONYMOUS' at source log mysql-bin-changelog.031523, end_log_pos 899; Could not execute Update_rows event on table test_replication.users; Can't find record in 'users', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's source log mysql-bin-changelog.031523, end_log_pos 899, Error_code: MY-001032
注意
MySQL 和 MariaDB 引擎的错误日志格式各不相同。有关如何检索日志的信息,请参阅查看和列出数据库日志文件。
诊断问题
要诊断复制失败,请执行以下操作:
-
查看副本错误日志,确定复制停止的位置。您可以使用
MY-010584作为搜索关键字。 -
在副本上运行
SHOW REPLICA STATUS\G(在 MySQL 8.0.22 之前为SHOW SLAVE STATUS\G),然后查看Last_Error列:Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'ANONYMOUS' at source log mysql-bin-changelog.031523, end_log_pos 899. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any. -
检查二进制日志文件名以及复制进程在副本实例上停止的位置。您可以在副本实例的错误日志中找到此信息。
分析二进制日志
要调查特定事务的复制失败,您可以使用 mysqlbinlogmysql-bin-changelog.031523 中,复制在 end_log_pos 位置 899 失败,您可以分析这个特定位置以确定失败的原因。
注意
end_log_pos 值表示失败事件的结束位置。在解码后的二进制日志输出中,查找哪个事件的 end_log_pos 与该值匹配。
使用 mysqlbinlog 实用程序下载并检查相关的二进制日志。为主实例使用端点。
$ mysqlbinlog --read-from-remote-server \ --host=<rds-endpoint> \ --port=3306 \ --user=<username> \ --password=<password> \ --base64-output=DECODE-ROWS -vv \ mysql-bin-changelog.031523 > decoded-binlog-file-name
注意
mysqlbinlog 实用程序是一款原生 MySQL 工具,可帮助您读取和解释二进制日志内容。有关访问 Amazon RDS 上的二进制日志的更多信息,请参阅访问 MySQL 二进制日志。
在写入器实例的二进制日志中,显示出写入器实例尝试更新 test_replication.users 表中 id=1 的记录:
#251104 21:13:13 server id 680788197 end_log_pos 899 CRC32 0x89b1e255 Update_rows: table id 101 flags: STMT_END_F ### UPDATE `test_replication`.`users` ### WHERE ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### @2='Test User' /* VARSTRING(400) meta=400 nullable=1 is_null=0 */ ### @3='updated4@example.com' /* VARSTRING(400) meta=400 nullable=1 is_null=0 */ ### @4=1762288260 /* TIMESTAMP(0) meta=0 nullable=1 is_null=0 */ ### SET ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### @2='Test User' /* VARSTRING(400) meta=400 nullable=1 is_null=0 */ ### @3='updated5@example.com' /* VARSTRING(400) meta=400 nullable=1 is_null=0 */ ### @4=1762288260 /* TIMESTAMP(0) meta=0 nullable=1 is_null=0 */ # at 899
副本的错误日志显示副本无法执行 UPDATE 语句,因为目标记录不存在:
Can't find record in 'users', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND
要验证该行是否缺失,请检查副本上是否存在该特定行:
SELECT 1 FROM test_replication.users WHERE id=1; Empty set (0.00 sec)
此输出确认源数据库实例的 UPDATE 操作复制失败,因为副本上不存在目标行。
避免复制失败
我们建议采用以下最佳实践来避免复制不一致的情况:
-
使用基于 GTID 的复制。有关更多信息,请参阅 使用基于 GTID 的复制。
-
在主实例上使用
binlog_format作为ROW。使用binlog_format作为MIXED,复制就有可能隐藏不一致之处而不提示。 -
在副本实例上将
read_only配置为1可防止意外修改行。 -
在副本实例上将
innodb_flush_log_at_trx_commit设置为1。 -
在主实例上将
sync_binlog设置为1。 -
验证主实例与副本之间的表架构奇偶校验。
-
确保复制的表具有主键。