Bug #79610 | Failed DROP DATABASE due FK constraint on master breaks slave | ||
---|---|---|---|
Submitted: | 11 Dec 2015 21:18 | Modified: | 7 May 2019 9:54 |
Reporter: | Sveta Smirnova (OCA) | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Replication | Severity: | S3 (Non-critical) |
Version: | 5.5.46, 5.6.27, 5.7.9, 5.5.48, 5.6.28 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | Contribution |
[11 Dec 2015 21:18]
Sveta Smirnova
[11 Dec 2015 21:20]
Sveta Smirnova
Option file: --replicate-ignore-db=db1 --replicate-wild-ignore-table=db1.%
[13 Dec 2015 13:45]
MySQL Verification Team
Hello Sveta, Thank you for the report and test case. Verified as described with 5.5.48, 5.6.28 builds. Thanks, Umesh
[13 Dec 2015 13:46]
MySQL Verification Team
test results
Attachment: 79610.results (application/octet-stream, text), 30.76 KiB.
[14 Dec 2015 18:49]
hussain patel
Can you please test this with a drop table and delete a row with parent child relation on master. I doubt if it will work in that case too.
[15 Jan 2016 11:34]
Sveta Smirnova
If just replace in my test "DROP DATABASE db2;" with "DROP TABLE db2.a1, db2.a2, db2.table0, db2.table1;" slave would not fail, because DROP TABLE statement will be correctly prefixed with USE db1: show binlog events; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 120 Server ver: 5.6.28-76.1-debug-log, Binlog ver: 4 ... master-bin.000001 1138 Query 1 1298 use `db1`; DROP TABLE `db2`.`a1`,`db2`.`a2`,`db2`.`table0`,`db2`.`table1` /* generated by server */ show slave status; In case of DROP DATABASE it not only creates dangerous statement, it also calls this command from wrong database: show binlog events; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 120 Server ver: 5.6.28-76.1-debug-log, Binlog ver: 4 ... master-bin.000001 1138 Query 1 1249 use `db2`; DROP TABLE IF EXISTS `a1`,`a2`,`table0` Another interesting finding: if I just replace "DROP DATABASE db2;" with "USE db2; DROP TABLE db2.a1, db2.a2, db2.table0, db2.table1;" or "USE db2; DROP TABLE a1, a2, table0, table1;" slave, again, would not fail. But if I remove from the list last table, table1, which caused error on master (" DROP TABLE IF EXISTS a1, a2, table0"), slave will fail again.
[5 Aug 2017 7:27]
Laurynas Biveinis
Bug 79610 fix for 8.0.2 (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug79610-8.0.2.patch (application/octet-stream, text), 18.09 KiB.
[2 Feb 2018 7:32]
Laurynas Biveinis
The latest contributed fix applies cleanly and works on 8.0.4 too.
[13 Jun 2018 12:31]
Laurynas Biveinis
Bug 79610 fix for 8.0.11 (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug79610-8.0.11.patch (application/octet-stream, text), 19.67 KiB.
[14 Jun 2018 5:04]
MySQL Verification Team
Thank you for the contributions! Regards, Umesh
[8 Aug 2018 10:39]
Laurynas Biveinis
Fixed in 8.0.12? commit d408eb3145e19ed95e01804adccd27b0b1bb612c Author: Dmitry Lenev <dmitry.lenev@oracle.com> Date: Tue Apr 10 13:07:52 2018 +0300 Bug#27821060 "NEWDD FK: DROP TABLES/DATABASE SHOULD CHECK FOR FKS". After we have started to store information about foreign keys in the New Data Dictionary it became possible to move checks of foreign key definition validity from the storage engine to SQL-layer and thus reduce code duplication and simplify SE implementation. This patch moves check that disallows dropping of parent table in a foreign key without prior dropping of child table from InnoDB SE to SQL-layer code implementing DROP TABLES/DROP DATABASE. Such check now happens before trying to delete any tables mentioned in DROP TABLES statement/belonging to schema to be dropped. So DROP TABLES/DROP DATABASE no longer have any side-effect even on tables in SEs which don't support atomic DDL when they fail due to this check. The check was also relaxed to allow dropping of parent and child table in arbitrary order as long as they are dropped by the same DROP TABLES statement. This is possible thanks to the fact that both our engines supporting foreign keys also support atomic DDL. Finally, error message which is emitted when user attempts to drop parent table without dropping child was changed to more verbose one. New test coverage for this check was added and existing tests were adjusted accordingly. Also, some test cases which previously used foreign key dependency as a way to fail DROP TABLES/DATABASE in the middle of their execution had to be adjusted to rely on error injection instead.
[15 Apr 2019 15:57]
Dmitry Lenev
Posted by developer: Hello! The problem is no longer repeatable in recent 8.0 versions. Here is what slightly modified test case gives me on 8.0.18-git: === --source include/master-slave.inc CREATE DATABASE `db2`; USE `db2`; CREATE TABLE a1(f1 INT); CREATE TABLE a2(f1 INT); CREATE TABLE `table0` (`ID` bigint(20) primary key) ENGINE=InnoDB; CREATE TABLE `table1` (`ID` bigint(20) primary key) ENGINE=InnoDB; CREATE DATABASE db1; USE db1; 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 `db2`.`table1` (`ID`) ON DELETE no action ) ENGINE=InnoDB; # The below DROP DATABASE fails with a new error in 8.0 # ERROR HY000: Cannot drop table 'table1' referenced by a foreign key constraint 'FK_TABLE1_DIVISION_1' on table 'table2'. --error 3730 DROP DATABASE db2; SHOW BINLOG EVENTS; # Returns. # Log_name Pos Event_type Server_id End_log_pos Info # master-bin.000001 4 Format_desc 1 124 Server ver: 8.0.18-tr-cluster, Binlog ver: 4 # master-bin.000001 124 Previous_gtids 1 155 # master-bin.000001 155 Anonymous_Gtid 1 232 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 232 Query 1 339 CREATE DATABASE `db2` /* xid=196 */ # master-bin.000001 339 Anonymous_Gtid 1 416 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 416 Query 1 525 use `db2`; CREATE TABLE a1(f1 INT) /* xid=198 */ # master-bin.000001 525 Anonymous_Gtid 1 602 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 602 Query 1 711 use `db2`; CREATE TABLE a2(f1 INT) /* xid=199 */ # master-bin.000001 711 Anonymous_Gtid 1 788 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 788 Query 1 939 use `db2`; CREATE TABLE `table0` (`ID` bigint(20) primary key) ENGINE=InnoDB /* xid=200 */ # master-bin.000001 939 Anonymous_Gtid 1 1016 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 1016 Query 1 1167 use `db2`; CREATE TABLE `table1` (`ID` bigint(20) primary key) ENGINE=InnoDB /* xid=201 */ # master-bin.000001 1167 Anonymous_Gtid 1 1244 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 1244 Query 1 1349 CREATE DATABASE db1 /* xid=202 */ # master-bin.000001 1349 Anonymous_Gtid 1 1428 SET @@SESSION.GTID_NEXT= 'ANONYMOUS' # master-bin.000001 1428 Query 1 1812 use `db1`; 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 `db2`.`table1` (`ID`) ON DELETE no # action ) ENGINE=InnoDB /* xid=204 */ ==== Notice that there is no trace of failed DROP DATABASE in binary log at all. This is because after fix for bug#27821060 "NEWDD FK: DROP TABLES/DATABASE SHOULD CHECK FOR FKS" in 8.0.12 both DROP DATABASE now checks first if any tables to be deleted is referenced by foreign key outside of database and fails early, without side-effects if it is. Moreover, the problem should not be repeatable in 8.0 even before this fix as thanks to introduction of atomic DDL support there, partial DROP DATABASE statements on InnoDB-only databases are impossible, as error in the middle of such statement causes its full rollback (and the problem is not relevant for MyISAM tables as they don't support foreign keys anyway). Taking into account the above I am closing this bug as fixed in 8.0.12. Moving it to Documenting state to let Documentation team to decide if they want to emphasize the fact that DROP DATABASE/TABLES now check for referenced FKs before deleting anything in release notes.
[7 May 2019 9:54]
Erlend Dahl
Fixed in 8.0.12. Posted by doc responsible: Margaret Fisher Added bug number and extra info to changelog entry for Bug #27821060 / 90320, which now reads: Checking for foreign key relationships by DROP TABLE and DROP DATABASE was improved. The check now takes place before any tables are deleted, so that in the event of a problem the statement fails before making any changes. Parent and child tables now can be dropped in arbitrary order, as long as they are dropped by the same DROP TABLE statement. In addition, error reporting was improved for attempts to drop a parent table without dropping a child table.