共计 2389 个字符,预计需要花费 6 分钟才能阅读完成。
MySQL 主从复制中断,报“Error on master: message (format)=’Cannot delete or update a parent row: a foreign key constraint fails’ error code=1217”错误。
前几天,发现从库挂了,具体报错信息如下:
分析思路
1. 因为我采用的是选择性复制,只针对以下几个库进行复制:card,upay,deal,monitor,collect。所以,不太可能出现对于 sas_basic 的操作能复制到该从库上。
2. 整个架构是 1 主 2 从,且都是选择性复制,上面这个从库是直接复制 card,upay,deal,monitor,collect 这几个数据库的数据,而另外一个从库则是忽略上述库,如下所示:
怀疑是在上述 schema 下,执行了 DROP TABLE IF EXISTS `sas_basic.old_channel_code` 操作。
3. 于是根据报错信息查看了主库 binlog 日志的内容,发现是在 sas_basic schema 下操作的。
use `sas_basic`/*!*/;
困惑
针对 sas_basic 的操作为什么会反映到不复制它操作的从库上。
PS:根据上述报错信息,中途还怀疑主从库的外键定义不一致导致上述问题的产生,后来查看,发现主从库的外键定义是一致的。
原因
上次利用 set global sql_slave_skip_counter= 1 跳过后,今天又碰到了这个问题,深入其中,才发现这是 MySQL 的一个 bug:https://bugs.mysql.com/bug.php?id=77684
但是这个 bug 中涉及到的版本是 5.6.25, 5.6.27。而我生产数据库是 5.6.26。于是,在测试机上搭建环境,看能否重现问题。
重现现场
还是一主两从,其中一个从设置 replicate-ignore-db=test,另外一个从设置 replicate-do-db=test。
在主中执行以下语句:
CREATE DATABASE `db1`;
USE `db1`;
CREATE TABLE `table1` (`ID` bigint(20) primary key) ENGINE=InnoDB;
CREATE TABLE `table2` (`ID` bigint(20) NOT NULL AUTO_INCREMENT, `DIVISION_ID` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`), KEY `FK_TABLE1_DIVISION_1` (`DIVISION_ID`), CONSTRAINT `FK_TABLE1_DIVISION_1` FOREIGN KEY (`DIVISION_ID`) REFERENCES `table1` (`ID`) ON DELETE CASCADE ) ENGINE=InnoDB;
DROP TABLE IF EXISTS `table1`;
结果,replicate-ignore-db=test 这个从库中复制正常,但 replicate-do-db=test 这个从库的复制却出现问题。报如下错误:
Last_SQL_Error: Query caused different errors on master and slave. Error on master: message (format)=’Cannot delete or update a parent row: a foreign key constraint fails’ error code=1217 ; Error on slave: actual message=’no error’, error code=0. Default database: ‘db1’. Query: ‘DROP TABLE IF EXISTS `table1` /* generated by server */’
Replicate_Ignore_Server_Ids:
完美重现现场。
提交这个 Bug 的哥们同时也给出了一种替代方案
Suggested fix:
The problem seems to be related to the “USE” above as the following works as expected:
CREATE DATABASE `db1`;
CREATE TABLE `db1`.`table1` (`ID` bigint(20) primary key) ENGINE=InnoDB;
CREATE TABLE `db1`.`table2` (`ID` bigint(20) NOT NULL AUTO_INCREMENT, `DIVISION_ID` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`), KEY `FK_TABLE1_DIVISION_1` (`DIVISION_ID`), CONSTRAINT `FK_TABLE1_DIVISION_1` FOREIGN KEY (`DIVISION_ID`) REFERENCES `db1`.`table1` (`ID`) ON DELETE CASCADE ) ENGINE=InnoDB;
DROP TABLE IF EXISTS `db1`.`table1`;
however if you add an USE `db1` after the CREATE DATABASE statement the replication error will follow.
即在其它 schema 中删除该表。
但经过测试,无论是在其它 schema 中执行该操作还是不指定数据库执行该操作,均会使得复制中断。
总结:
1. 该 Bug 不仅仅在 replicate-ignore-db 会触发,在 replicate-do-db 中也会触发。
2. 官方承诺会在 5.6.30 和 5.7.12 修复,具体未测。
本文永久更新链接地址 :http://www.linuxidc.com/Linux/2016-05/131247.htm