mariadb/mysql-test/suite/innodb/t/truncate_foreign.test
Monty 676987c4a1 MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE .. on table with foreign key
When doing a truncate on an Innodb under lock tables, InnoDB would rename
the old table to #sql-... and recreate a new 't1' table. The table lock
would still be on the #sql-table.

When doing ALTER TABLE, Innodb would do the changes on the #sql table
(which would disappear on close).
When the SQL layer, as part of inline alter table, would close the
original t1 table (#sql in InnoDB) and then reopen the t1 table, Innodb
would notice that this does not match it's own (old) t1 table and
generate an error.

Fixed by adding code in truncate table that if we are under lock tables
and truncating an InnoDB table, we would close, reopen and lock the
table after truncate. This will remove the #sql table and ensure that
lock tables is using the new empty table.

Reviewer: Marko Mäkelä
2021-03-02 15:23:56 +02:00

82 lines
1.9 KiB
Text

--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
CREATE TABLE parent (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO parent SET a=1;
CREATE TABLE child (a INT PRIMARY KEY, FOREIGN KEY (a) REFERENCES parent(a)
ON UPDATE CASCADE)
ENGINE=InnoDB;
INSERT INTO child SET a=1;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE parent;
TRUNCATE TABLE child;
INSERT INTO child SET a=1;
UPDATE parent SET a=2;
SELECT * FROM child;
connect (dml,localhost,root);
SET DEBUG_SYNC='foreign_constraint_update_cascade SIGNAL fk WAIT_FOR go';
send UPDATE parent SET a=3;
connection default;
SET DEBUG_SYNC='now WAIT_FOR fk';
SET lock_wait_timeout=1;
--error ER_LOCK_WAIT_TIMEOUT
TRUNCATE TABLE child;
SET DEBUG_SYNC='now SIGNAL go';
connection dml;
reap;
SELECT * FROM child;
SET DEBUG_SYNC='foreign_constraint_check_for_update SIGNAL fk WAIT_FOR go';
send DELETE FROM parent;
connection default;
SET DEBUG_SYNC='now WAIT_FOR fk';
SET lock_wait_timeout=1;
--error ER_LOCK_WAIT_TIMEOUT
TRUNCATE TABLE child;
SET DEBUG_SYNC='now SIGNAL go';
connection dml;
--error ER_ROW_IS_REFERENCED_2
reap;
SELECT * FROM child;
INSERT INTO parent SET a=5;
SET DEBUG_SYNC='foreign_constraint_check_for_ins SIGNAL fk WAIT_FOR go';
send INSERT INTO child SET a=5;
connection default;
SET DEBUG_SYNC='now WAIT_FOR fk';
SET foreign_key_checks=0;
TRUNCATE TABLE parent;
SET DEBUG_SYNC='now SIGNAL go';
connection dml;
--error ER_NO_REFERENCED_ROW_2
reap;
SELECT * FROM parent;
SELECT * FROM child;
disconnect dml;
connection default;
SET DEBUG_SYNC = RESET;
DROP TABLE child, parent;
--echo #
--echo # MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE or
--echo # ER_CRASHED_ON_USAGE after ALTER on table with foreign key
--echo #
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES t1 (a) ON UPDATE CASCADE;
LOCK TABLE t1 WRITE;
TRUNCATE TABLE t1;
ALTER TABLE t1 ADD c INT;
UNLOCK TABLES;
DROP TABLE t1;