diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result new file mode 100644 index 00000000000..0d04f27f51f --- /dev/null +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -0,0 +1,19 @@ +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; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test new file mode 100644 index 00000000000..223a1596883 --- /dev/null +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -0,0 +1,25 @@ +--source include/have_innodb.inc + +# +# 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; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a1ffa239ef4..be87ad27d6b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4893,8 +4893,9 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx, else lock_type= TL_READ; - if (table_already_fk_prelocked(table_list, fk->foreign_db, - fk->foreign_table, lock_type)) + if (table_already_fk_prelocked(prelocking_ctx->query_tables, + fk->foreign_db, fk->foreign_table, + lock_type)) continue; TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));