mirror of
https://github.com/MariaDB/server.git
synced 2025-07-16 00:42:55 +03:00
MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE
table_already_fk_prelocked() was looking for a table in the wrong list (not the complete list of prelocked tables, but only in its tail, starting from the current table - which is always empty for the last added table), so for circular FKs it kept adding same tables to the list indefinitely.
This commit is contained in:
@ -150,3 +150,22 @@ unique_constraint_name
|
|||||||
PRIMARY
|
PRIMARY
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
SET FOREIGN_KEY_CHECKS=0;
|
||||||
|
CREATE TABLE staff (
|
||||||
|
staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
store_id TINYINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (staff_id),
|
||||||
|
KEY idx_fk_store_id (store_id),
|
||||||
|
CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE store (
|
||||||
|
store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
manager_staff_id TINYINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (store_id),
|
||||||
|
UNIQUE KEY idx_unique_manager (manager_staff_id),
|
||||||
|
CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
SET FOREIGN_KEY_CHECKS=DEFAULT;
|
||||||
|
LOCK TABLE staff WRITE;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
DROP TABLES staff, store;
|
||||||
|
@ -113,3 +113,27 @@ WHERE table_name = 't2';
|
|||||||
|
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE
|
||||||
|
#
|
||||||
|
SET FOREIGN_KEY_CHECKS=0;
|
||||||
|
CREATE TABLE staff (
|
||||||
|
staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
store_id TINYINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (staff_id),
|
||||||
|
KEY idx_fk_store_id (store_id),
|
||||||
|
CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE store (
|
||||||
|
store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
manager_staff_id TINYINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (store_id),
|
||||||
|
UNIQUE KEY idx_unique_manager (manager_staff_id),
|
||||||
|
CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
SET FOREIGN_KEY_CHECKS=DEFAULT;
|
||||||
|
|
||||||
|
LOCK TABLE staff WRITE;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
DROP TABLES staff, store;
|
||||||
|
@ -4255,8 +4255,9 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
|||||||
else
|
else
|
||||||
lock_type= TL_READ;
|
lock_type= TL_READ;
|
||||||
|
|
||||||
if (table_already_fk_prelocked(table_list, fk->foreign_db,
|
if (table_already_fk_prelocked(prelocking_ctx->query_tables,
|
||||||
fk->foreign_table, lock_type))
|
fk->foreign_db, fk->foreign_table,
|
||||||
|
lock_type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
|
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
|
||||||
|
Reference in New Issue
Block a user