1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

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 9de2e60d74 there
will be no problems to enforce subsequent FOREIGN KEY operations
even though a table with invalid REFERENCES clause was loaded.
This commit is contained in:
Marko Mäkelä
2022-04-19 12:40:05 +03:00
parent e4e25d2bac
commit 5aef0123a7
3 changed files with 63 additions and 2 deletions

View File

@ -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

View File

@ -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;

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
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 {
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