1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-32899 InnoDB is holding shared dict_sys.latch while waiting for FOREIGN KEY child table lock on DDL

lock_table_children(): A new function to lock all child tables of a table.
We will only hold dict_sys.latch while traversing
dict_table_t::referenced_set. To prevent a race condition with
std::set::erase() we will copy the pointers to the child tables to a
local vector. Once we have acquired MDL and references to all child tables,
we can safely release dict_sys.latch, wait for the locks, and finally
release the references.

dict_acquire_mdl_shared(): A new variant that takes mdl_context as a
parameter.

lock_table_for_trx(): Assert that we are not holding dict_sys.latch.

ha_innobase::truncate(): When foreign_key_checks=ON, assert that
no child tables exist (other than the current table).
In any case, we will invoke lock_table_children()
so that the child table metadata can be safely updated.
(It is possible that a child table is being created concurrently
with TRUNCATE TABLE.)

ha_innobase::delete_table(): Before and after acquiring exclusive
locks on the current table as well as all child tables,
check that FOREIGN KEY constraints will not be violated.
In this way, we can reject impossible DROP TABLE without having to
wait for locks first.

This fixes up commit 2ca1123464 (MDEV-26217)
and commit c3c53926c4 (MDEV-26554).
This commit is contained in:
Marko Mäkelä
2024-02-01 15:48:46 +02:00
committed by Daniel Black
parent 5f2dcd112b
commit b2654ba826
8 changed files with 248 additions and 94 deletions

View File

@@ -1077,10 +1077,23 @@ BEGIN;
--error ER_NO_REFERENCED_ROW_2
INSERT INTO child SET a=1;
connection default;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE parent;
--error ER_ROW_IS_REFERENCED_2
DROP TABLE parent;
SET innodb_lock_wait_timeout=0;
--error ER_LOCK_WAIT_TIMEOUT
RENAME TABLE parent TO transparent;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=COPY;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
SET innodb_lock_wait_timeout=0, foreign_key_checks=0;
--error ER_LOCK_WAIT_TIMEOUT
TRUNCATE TABLE parent;
--error ER_LOCK_WAIT_TIMEOUT
DROP TABLE parent;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=COPY;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
@@ -1095,7 +1108,13 @@ TRUNCATE TABLE parent;
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
ALTER TABLE parent ADD COLUMN b INT, ALGORITHM=INSTANT;
DROP TABLE child, parent;
SET foreign_key_checks=ON;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE parent;
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
RENAME TABLE parent TO transparent;
DROP TABLE child, transparent;
--echo #
--echo # MDEV-26217 Failing assertion: list.count > 0 in ut_list_remove