MariaDB主从复制执行删除操作时出现1032错误的排查与解决
看起来你遇到了MariaDB主从复制里非常典型的一致性问题——初始同步后一切正常,但主库执行删除操作时,从库因为找不到对应记录直接导致SQL线程挂掉了。我来帮你一步步拆解问题根源,以及给出可落地的解决办法。
先搞懂错误本质
错误码1032(HA_ERR_KEY_NOT_FOUND)的核心原因是主从数据不一致:主库要删除的那条记录,在从库的对应表里根本不存在。初始同步后明明状态正常,为什么过一会就出现这种情况?大概率是你部署复制的流程里藏着细节问题,或者主从的配置不符合最佳实践。
结合你的Ansible配置排查问题点
我仔细看了你的自动化流程,发现几个可能踩坑的地方:
1. 手动执行CHANGE MASTER TO和dump文件的配置冲突了
你用了--apply-slave-statements参数生成dump文件,这个参数会自动在备份文件里写入CHANGE MASTER TO语句(包含--master-data=1记录的正确binlog位置),同时自动执行START SLAVE。但你在导入dump前,手动执行了一遍CHANGE MASTER TO,这会导致:
- 从库先被设置了一次复制参数,导入dump时又被覆盖一次
- 极有可能出现复制起点不匹配的情况,导致从库跳过了部分主库操作,直接埋下数据不一致的隐患
2. 备份时可能没保证InnoDB表的一致性
你的mysqldump命令没加--single-transaction参数,虽然--master-data=1会默认锁全表,但如果你的Nextcloud用的是InnoDB引擎(大部分都是),加这个参数可以在不锁全表的前提下,通过事务快照获取一致性备份,避免锁表期间的写操作阻塞,同时保证备份数据和binlog起点完全对齐。
3. 可能用了不安全的binlog格式
如果主库的binlog_format是STATEMENT模式,一些非确定性语句(比如带LIMIT的DELETE、依赖会话变量的操作)在主从执行的结果可能不一样,很容易导致数据差异。而ROW模式会记录行的实际变化,从库直接应用行变更,能避免这类问题。
具体解决步骤
第一步:修正Ansible的复制部署流程
把手动配置从库的步骤删掉,让dump文件自带的配置来完成复制初始化,调整后的关键步骤如下:
# 主库生成备份(添加--single-transaction保证InnoDB一致性) - name: Backup all databases for replication when: inventory_hostname == mariadb_master_host community.mysql.mysql_db: login_user: admin login_password: "{{ passwd }}" config_file: "" state: dump master_data: 1 dump_extra_args: "--apply-slave-statements --single-transaction" name: - db1 - db2 - nextcloud target: "/tmp/mariadb.dump.{{ datetime }}.sql.gz" pipefail: true # 从库先清空之前的复制配置 - name: Reset Slave configuration when: inventory_hostname != mariadb_master_host community.mysql.mysql_query: login_user: admin login_password: "{{ passwd.stdout }}" query: RESET SLAVE ALL; # 导入dump文件(自动完成CHANGE MASTER和START SLAVE) - name: Import MariaDB Dump to start replication when: inventory_hostname != mariadb_master_host community.mysql.mysql_db: login_user: admin login_password: "{{ passwd.stdout }}" state: import target: "/tmp/mariadb.dump.{{ datetime }}.sql.gz" name: all config_file: "" pipefail: true use_shell: true
第二步:强制主从使用ROW格式的binlog
在主库和从库的配置文件(my.cnf或my.ini)里添加/修改:
[mysqld] binlog_format = ROW
修改后重启MariaDB服务,确保配置生效。
第三步:处理当前从库的错误
现在从库SQL线程已经停止,你可以先临时跳过这个错误,然后再做一致性校验:
-- 在从库执行 SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;
⚠️ 这只是临时应急,必须后续验证数据一致性!
第四步:验证并修复主从数据一致性
用MariaDB自带的工具或者Percona的pt-table-checksum来检查主从表的一致性,重点检查nextcloud.oc_calendarobjects表:
-- 在主库执行,生成校验值 CHECKSUM TABLE nextcloud.oc_calendarobjects; -- 在从库执行同样命令,对比结果 CHECKSUM TABLE nextcloud.oc_calendarobjects;
如果结果不一致,可以用pt-table-sync工具同步数据,或者重新单独备份恢复这个表。
第五步:确保从库是只读状态
禁止任何直接写入从库的操作,所有写请求必须走主库,避免人为导致的数据不一致:
-- 在从库执行 SET GLOBAL read_only = ON;
也可以在配置文件里添加read_only = ON,永久生效。
额外注意事项
- 确保主从的MariaDB版本一致,版本差异可能导致复制兼容性问题
- 检查复制用户
replication的权限,必须拥有REPLICATION SLAVE权限 - 主库的
binlog_do_db和从库的replicate_do_db配置要匹配,避免漏同步或错同步
备注:内容来源于stack exchange,提问作者Karsten S.

