Commit a21e01a5 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-17541 KILL QUERY during lock wait in FOREIGN KEY check causes hang

row_ins_check_foreign_constraint(): Do not overwrite hard errors
with the soft error DB_LOCK_WAIT. This prevents an infinite
wait loop when DB_INTERRUPTED was returned. For DB_LOCK_WAIT,
row_insert_for_mysql() would keep invoking row_ins_step() and the
transaction would remain active until the server shutdown is initiated.
parent ab1ce220
...@@ -252,7 +252,6 @@ DELETE FROM t1 WHERE id = 1; ...@@ -252,7 +252,6 @@ DELETE FROM t1 WHERE id = 1;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
connection con1; connection con1;
COMMIT; COMMIT;
disconnect con1;
connection default; connection default;
SELECT * FROM t2; SELECT * FROM t2;
id ref_id f id ref_id f
...@@ -332,7 +331,25 @@ PRIMARY KEY (store_id), ...@@ -332,7 +331,25 @@ PRIMARY KEY (store_id),
UNIQUE KEY idx_unique_manager (manager_staff_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 CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB; ) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS=DEFAULT;
LOCK TABLE staff WRITE; LOCK TABLE staff WRITE;
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLES staff, store; DROP TABLES staff, store;
SET FOREIGN_KEY_CHECKS=1;
#
# MDEV-17541 KILL QUERY during lock wait in FOREIGN KEY check hangs
#
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (a INT PRIMARY KEY, FOREIGN KEY (a) REFERENCES t1(a))
ENGINE=InnoDB;
connection con1;
INSERT INTO t1 SET a=1;
BEGIN;
DELETE FROM t1;
connection default;
INSERT INTO t2 SET a=1;
connection con1;
kill query @id;
connection default;
ERROR 70100: Query execution was interrupted
disconnect con1;
DROP TABLE t2,t1;
...@@ -228,7 +228,6 @@ DELETE FROM t1 WHERE id = 1; ...@@ -228,7 +228,6 @@ DELETE FROM t1 WHERE id = 1;
--connection con1 --connection con1
COMMIT; COMMIT;
--disconnect con1
--connection default --connection default
SELECT * FROM t2; SELECT * FROM t2;
...@@ -288,8 +287,6 @@ insert into t1 values(1, 1); ...@@ -288,8 +287,6 @@ insert into t1 values(1, 1);
insert into t2(f1) values(1); insert into t2(f1) values(1);
drop table t2, t1; drop table t2, t1;
--source include/wait_until_count_sessions.inc
# #
# MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE # MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE
# #
...@@ -308,8 +305,42 @@ CREATE TABLE store ( ...@@ -308,8 +305,42 @@ CREATE TABLE store (
UNIQUE KEY idx_unique_manager (manager_staff_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 CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB; ) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS=DEFAULT;
LOCK TABLE staff WRITE; LOCK TABLE staff WRITE;
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLES staff, store; DROP TABLES staff, store;
SET FOREIGN_KEY_CHECKS=1;
--echo #
--echo # MDEV-17541 KILL QUERY during lock wait in FOREIGN KEY check hangs
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (a INT PRIMARY KEY, FOREIGN KEY (a) REFERENCES t1(a))
ENGINE=InnoDB;
connection con1;
INSERT INTO t1 SET a=1;
BEGIN;
DELETE FROM t1;
connection default;
let $ID= `SELECT @id := CONNECTION_ID()`;
send INSERT INTO t2 SET a=1;
connection con1;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = 'update' and info = 'INSERT INTO t2 SET a=1';
--source include/wait_condition.inc
let $ignore= `SELECT @id := $ID`;
kill query @id;
connection default;
--error ER_QUERY_INTERRUPTED
reap;
disconnect con1;
DROP TABLE t2,t1;
--source include/wait_until_count_sessions.inc
...@@ -1871,9 +1871,12 @@ row_ins_check_foreign_constraint( ...@@ -1871,9 +1871,12 @@ row_ins_check_foreign_constraint(
thr->lock_state = QUE_THR_LOCK_NOLOCK; thr->lock_state = QUE_THR_LOCK_NOLOCK;
if (check_table->to_be_dropped err = trx->error_state;
|| trx->error_state == DB_LOCK_WAIT_TIMEOUT) { if (err != DB_SUCCESS) {
} else if (check_table->to_be_dropped) {
err = DB_LOCK_WAIT_TIMEOUT; err = DB_LOCK_WAIT_TIMEOUT;
} else {
err = DB_LOCK_WAIT;
} }
my_atomic_addlint(&check_table->n_foreign_key_checks_running, my_atomic_addlint(&check_table->n_foreign_key_checks_running,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment