Commit 5aef0123 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-28317 Assertion failures in row_undo_mod on recovery

Starting with 10.3, an assertion would fail on the rollback of
a recovered incomplete transaction if a table definition violates
a FOREIGN KEY constraint.

DICT_ERR_IGNORE_RECOVER_LOCK: Include also DICT_ERR_IGNORE_FK_NOKEY
so that trx_resurrect_table_locks() will be able to load
table definitions and resurrect IX locks. Previously, if the
FOREIGN KEY constraints of a table were incomplete, the table
would fail to load until rollback, and in 10.3 or later an assertion
would fail that the rollback was not protected by a table IX lock.

Thanks to commit 9de2e60d there
will be no problems to enforce subsequent FOREIGN KEY operations
even though a table with invalid REFERENCES clause was loaded.
parent e4e25d2b
...@@ -137,6 +137,33 @@ SELECT unique_constraint_name FROM information_schema.referential_constraints ...@@ -137,6 +137,33 @@ SELECT unique_constraint_name FROM information_schema.referential_constraints
WHERE table_name = 't2'; WHERE table_name = 't2';
unique_constraint_name unique_constraint_name
PRIMARY PRIMARY
#
# MDEV-28317 Assertion failure on rollback of FOREIGN KEY operation
#
SET foreign_key_checks=0;
CREATE TABLE parent(a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE child(a INT,FOREIGN KEY(a) REFERENCES parent(a) ON DELETE CASCADE)
ENGINE=InnoDB;
INSERT INTO child VALUES(1);
ALTER TABLE child DROP INDEX a;
connect incomplete, localhost, root,,;
BEGIN;
DELETE FROM child;
connection default;
INSERT INTO parent SET a=0;
FLUSH TABLES;
disconnect incomplete;
INSERT INTO child SET a=0;
INSERT INTO child SET a=1;
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE)
DELETE FROM parent;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE)
ALTER TABLE child ADD INDEX(a);
DELETE FROM parent;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE)
ALTER TABLE child FORCE;
DELETE FROM parent;
DROP TABLE child,parent;
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SELECT unique_constraint_name FROM information_schema.referential_constraints SELECT unique_constraint_name FROM information_schema.referential_constraints
......
...@@ -102,7 +102,41 @@ INSERT INTO t2 VALUES (1); ...@@ -102,7 +102,41 @@ INSERT INTO t2 VALUES (1);
SELECT unique_constraint_name FROM information_schema.referential_constraints SELECT unique_constraint_name FROM information_schema.referential_constraints
WHERE table_name = 't2'; WHERE table_name = 't2';
--echo #
--echo # MDEV-28317 Assertion failure on rollback of FOREIGN KEY operation
--echo #
SET foreign_key_checks=0;
CREATE TABLE parent(a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE child(a INT,FOREIGN KEY(a) REFERENCES parent(a) ON DELETE CASCADE)
ENGINE=InnoDB;
INSERT INTO child VALUES(1);
ALTER TABLE child DROP INDEX a;
connect(incomplete, localhost, root,,);
BEGIN;
DELETE FROM child;
connection default;
INSERT INTO parent SET a=0;
FLUSH TABLES;
--let $shutdown_timeout=0
--source include/restart_mysqld.inc --source include/restart_mysqld.inc
--let $shutdown_timeout=
disconnect incomplete;
INSERT INTO child SET a=0;
--error ER_NO_REFERENCED_ROW_2
INSERT INTO child SET a=1;
--error ER_ROW_IS_REFERENCED_2
DELETE FROM parent;
ALTER TABLE child ADD INDEX(a);
--error ER_ROW_IS_REFERENCED_2
DELETE FROM parent;
ALTER TABLE child FORCE;
DELETE FROM parent;
DROP TABLE child,parent;
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -64,7 +64,7 @@ enum dict_err_ignore_t { ...@@ -64,7 +64,7 @@ enum dict_err_ignore_t {
DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root
page is FIL_NULL or incorrect value */ page is FIL_NULL or incorrect value */
DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */ DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */
DICT_ERR_IGNORE_RECOVER_LOCK = 8, DICT_ERR_IGNORE_RECOVER_LOCK = 8 | DICT_ERR_IGNORE_FK_NOKEY,
/*!< Used when recovering table locks /*!< Used when recovering table locks
for resurrected transactions. for resurrected transactions.
Silently load a missing Silently load a missing
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment