mirror of
https://github.com/MariaDB/server.git
synced 2025-12-28 08:10:14 +00:00
MDEV-29474 - main.lock_sync fails with timeout
Reimplement test for MDEV-28567 such that it behaves consistently and consistently covers the code that it was intended to cover. The test itself moved to mdl_sync.test, because lock_sync.test is supposed for testing THR_LOCK, not MDL. Verified with DBUG_ASSERT(0) in open_tables() (from92bfc0e8c4) restored. The test is failing with various symptoms as it was designed to be sporadic. It did cover the code that it was supposed to cover in less than 0.1% of runs. That is the following command succeeds often with DBUG_ASSERT(0) in open_tables() (from92bfc0e8c4) restored: ./mtr --repeat=25 --parallel=40 lock_sync{,,,,}{,,,,} Test is also reimplemented such that it doesn't rely on buggy "MDL overweight" behaviour as described in MDEV-36887. Previously it did require preceding statements that fall in deadlock in default connection. Now it works consistently in both cases: if there was preceding deadlock and if there was none. mdl_after_find_deadlock sync point added to avoid premature deadlock handling by connections that don't intend to handle it. ALTER VIEW connection is supposed to handle it, this makes test behaviour consistent. Tracking history:92bfc0e8c4MDEV-17554, assert addedf88511647aMDEV-28567, test added, assertion modifiedfe3adde250MDEV-29060, test moved, fix attempted8ee93b9cb4MDEV-29060, fix attempted611d442510fix attempted77c465d5aaassertion modified4c695c85bdassertion removed MDEV-29474 - subj MDEV-36665 - duplicate of MDEV-29474
This commit is contained in:
parent
060c0e3ff5
commit
bfbba94ead
@ -856,28 +856,3 @@ SET DEBUG_SYNC="RESET";
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
DROP TABLES t1, t2;
|
||||
#
|
||||
# MDEV-28567 Assertion `0' in open_tables upon function-related operation
|
||||
#
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (b INT);
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW UPDATE t2 SET b = 0;
|
||||
CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW UPDATE t1 SET a = 6;
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
SET AUTOCOMMIT=OFF;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP TRIGGER tr1;
|
||||
INSERT INTO t2 SELECT * FROM t2;
|
||||
SELECT f() FROM t2;
|
||||
ERROR 42000: FUNCTION test.f does not exist
|
||||
set debug_sync= 'after_open_table_mdl_shared signal s1';
|
||||
ALTER VIEW v1 AS SELECT f() FROM t1;
|
||||
CREATE FUNCTION f() RETURNS INT RETURN 1;
|
||||
set debug_sync= 'now wait_for s1';
|
||||
SELECT * FROM ( SELECT * FROM v1 ) sq;
|
||||
COMMIT;
|
||||
DROP VIEW v1;
|
||||
DROP FUNCTION IF EXISTS f;
|
||||
DROP TABLE t1, t2;
|
||||
set debug_sync= 'reset';
|
||||
|
||||
@ -1079,123 +1079,3 @@ DROP TABLES t1, t2;
|
||||
# Check that all connections opened by test cases in this file are really
|
||||
# gone so execution of other tests won't be affected by their presence.
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28567 Assertion `0' in open_tables upon function-related operation
|
||||
--echo #
|
||||
# To get MDL trace run this case like this:
|
||||
# mtr --mysqld=--debug=d,mdl,query:i:o,/tmp/mdl.log ...
|
||||
# Cleanup trace like this:
|
||||
# sed -i -re '/(mysql|performance_schema|sys|mtr)\// d; /MDL_BACKUP_|MDL_INTENTION_/ d; /\/(t2|tr1|tr2)/ d' /tmp/mdl.log
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (b INT);
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW UPDATE t2 SET b = 0;
|
||||
CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW UPDATE t1 SET a = 6;
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
|
||||
SET AUTOCOMMIT=OFF;
|
||||
SELECT * FROM t1;
|
||||
# T@6
|
||||
# Seized: test/t1 (MDL_SHARED_READ)
|
||||
|
||||
--connect (con1,localhost,root,,test)
|
||||
--send
|
||||
DROP TRIGGER tr1;
|
||||
# T@7
|
||||
# Seized: test/t1 (MDL_SHARED_NO_WRITE)
|
||||
# Waiting: test/t1 (MDL_EXCLUSIVE)
|
||||
# Waiting: test/t1 (MDL_SHARED_WRITE)
|
||||
# Deadlock: test/t1 (MDL_SHARED_WRITE)
|
||||
|
||||
--connection default
|
||||
--error 0, ER_LOCK_DEADLOCK
|
||||
INSERT INTO t2 SELECT * FROM t2;
|
||||
# T@6
|
||||
# Released: test/t1 (MDL_SHARED_READ)
|
||||
# T@7
|
||||
# Acquired: test/t1 (MDL_EXCLUSIVE) (good)
|
||||
--error ER_SP_DOES_NOT_EXIST
|
||||
SELECT f() FROM t2;
|
||||
# T@6
|
||||
# Seized: test/f (MDL_SHARED)
|
||||
# T@7
|
||||
# Released: test/t1 (MDL_EXCLUSIVE)
|
||||
# Good1: continue T@6 below
|
||||
# Bad1: continue T@8 below
|
||||
|
||||
# Now we hold test/f, the below code creates concurrent
|
||||
# waiting of 3 threads for test/f which leads to deadlock (Bad)
|
||||
|
||||
# To achive Good comment out 'now wait_for s1' below and run multiple times.
|
||||
|
||||
--connect (con2,localhost,root,,test)
|
||||
set debug_sync= 'after_open_table_mdl_shared signal s1';
|
||||
--send
|
||||
ALTER VIEW v1 AS SELECT f() FROM t1;
|
||||
# T@8
|
||||
# Good2: Waiting: test/v1 (MDL_EXCLUSIVE)
|
||||
# Good2-3: continue T@7 below
|
||||
# Good5: Acquired: test/v1 (MDL_EXCLUSIVE)
|
||||
# Good5: Seized: test/v1 (MDL_EXCLUSIVE)
|
||||
# Good5-6: continue T@7 below
|
||||
# Good7: Seized: test/t1 (MDL_SHARED_READ)
|
||||
# Good7: Waiting: test/f (MDL_SHARED)
|
||||
# Good7-8: continue T@7 below
|
||||
# Good9: Acquired: test/f (MDL_SHARED)
|
||||
# Good9: Released: test/f (MDL_SHARED)
|
||||
# Good9: Released: test/t1 (MDL_SHARED_READ)
|
||||
# Good9: Released: test/v1 (MDL_EXCLUSIVE)
|
||||
# Good9: command finished without error
|
||||
# Bad1: Seized: test/v1 (MDL_EXCLUSIVE)
|
||||
# Bad1: Seized: test/v1 (MDL_EXCLUSIVE)
|
||||
# Bad1: Seized: test/t1 (MDL_SHARED_READ)
|
||||
# Bad1-2: continue T@6 below
|
||||
# Bad4: Waiting: test/f (MDL_SHARED)
|
||||
# Bad4: Deadlock: test/f (MDL_SHARED)
|
||||
# Bad4: command finished with error
|
||||
|
||||
--connection con1
|
||||
--reap
|
||||
--send
|
||||
CREATE FUNCTION f() RETURNS INT RETURN 1;
|
||||
# T@7
|
||||
# Good3: Waiting: test/f (MDL_EXCLUSIVE)
|
||||
# Good3-4: continue T@6 below
|
||||
# Good6: Acquired: test/f (MDL_EXCLUSIVE)
|
||||
# Good6-7: continue T@8 above
|
||||
# Good8: Released: test/f (MDL_EXCLUSIVE)
|
||||
# Good8-9: continue T@8 above
|
||||
# Bad3: Waiting: test/f (MDL_EXCLUSIVE)
|
||||
# Bad3-4: continue T@8 above
|
||||
|
||||
--connection default
|
||||
set debug_sync= 'now wait_for s1';
|
||||
--disable_result_log
|
||||
SELECT * FROM ( SELECT * FROM v1 ) sq;
|
||||
--enable_result_log
|
||||
# T@6
|
||||
# Good1: Seized: test/v1 (MDL_SHARED_READ)
|
||||
# Good1-2: continue T@8 above
|
||||
# Good4: Seized: test/t1 (MDL_SHARED_READ)
|
||||
# Bad2: Waiting: test/v1 (MDL_SHARED_READ)
|
||||
# Bad2-3: continue T@7 above
|
||||
|
||||
# Cleanup
|
||||
COMMIT;
|
||||
# Good4: Released: test/t1 (MDL_SHARED_READ)
|
||||
# Good4: Released: test/v1 (MDL_SHARED_READ)
|
||||
# Good4: Released: test/f (MDL_SHARED)
|
||||
# Good4-5: continue T@8 above
|
||||
|
||||
--connection con2
|
||||
--error 0, ER_SP_DOES_NOT_EXIST
|
||||
--reap
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
--connection default
|
||||
--source include/wait_until_count_sessions.inc
|
||||
DROP VIEW v1;
|
||||
DROP FUNCTION IF EXISTS f;
|
||||
DROP TABLE t1, t2;
|
||||
set debug_sync= 'reset';
|
||||
|
||||
@ -3015,3 +3015,34 @@ connection default;
|
||||
SET debug_sync='RESET';
|
||||
DROP TABLE t1;
|
||||
disconnect con1;
|
||||
#
|
||||
# MDEV-28567 Assertion `0' in open_tables upon function-related operation
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT 1;
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
|
||||
connect con1, localhost, root;
|
||||
SET debug_sync='open_and_process_table SIGNAL ready1 WAIT_FOR go1';
|
||||
ALTER VIEW v1 AS SELECT f1();
|
||||
connect con2, localhost, root;
|
||||
SET debug_sync='now WAIT_FOR ready1';
|
||||
SET debug_sync='mdl_after_find_deadlock SIGNAL ready2';
|
||||
SELECT f1();
|
||||
connect con3, localhost, root;
|
||||
SET debug_sync='now WAIT_FOR ready2';
|
||||
SET debug_sync='mdl_after_find_deadlock SIGNAL ready3';
|
||||
DROP FUNCTION f1;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR ready3';
|
||||
SET debug_sync='now SIGNAL go1';
|
||||
connection con3;
|
||||
disconnect con3;
|
||||
connection con2;
|
||||
f1()
|
||||
1
|
||||
disconnect con2;
|
||||
connection con1;
|
||||
ERROR 42000: FUNCTION test.f1 does not exist
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP VIEW v1;
|
||||
SET debug_sync='reset';
|
||||
|
||||
@ -4010,6 +4010,58 @@ DROP TABLE t1;
|
||||
|
||||
disconnect con1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28567 Assertion `0' in open_tables upon function-related operation
|
||||
--echo #
|
||||
#
|
||||
# This test covers deadlock recovery code in open_tables() after
|
||||
# open_and_process_routine(). ALTER VIEW v1 connection must fall as a deadlock
|
||||
# victim to hit this code.
|
||||
#
|
||||
# default connection cannot be used since it may have deadlock weight spoiled
|
||||
# by "MDL deadlock overweight" feature from previous deadlocks. In this case
|
||||
# ALTER VIEW v1 won't fall as a deadlock victim and the test won't cover
|
||||
# intended code.
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT 1;
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
|
||||
|
||||
connect con1, localhost, root;
|
||||
SET debug_sync='open_and_process_table SIGNAL ready1 WAIT_FOR go1';
|
||||
send ALTER VIEW v1 AS SELECT f1(); # X v1, S f1
|
||||
|
||||
connect con2, localhost, root;
|
||||
SET debug_sync='now WAIT_FOR ready1';
|
||||
SET debug_sync='mdl_after_find_deadlock SIGNAL ready2';
|
||||
send SELECT f1(); # S f1, SR v1
|
||||
|
||||
connect con3, localhost, root;
|
||||
SET debug_sync='now WAIT_FOR ready2';
|
||||
SET debug_sync='mdl_after_find_deadlock SIGNAL ready3';
|
||||
send DROP FUNCTION f1; # X f1
|
||||
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR ready3';
|
||||
SET debug_sync='now SIGNAL go1';
|
||||
|
||||
connection con3;
|
||||
reap;
|
||||
disconnect con3;
|
||||
|
||||
connection con2;
|
||||
reap;
|
||||
disconnect con2;
|
||||
|
||||
connection con1;
|
||||
--error ER_SP_DOES_NOT_EXIST
|
||||
reap;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
DROP VIEW v1;
|
||||
SET debug_sync='reset';
|
||||
|
||||
# Check that all connections opened by test cases in this file are really
|
||||
# gone so execution of other tests won't be affected by their presence.
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
@ -2396,6 +2396,8 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
|
||||
|
||||
find_deadlock();
|
||||
|
||||
DEBUG_SYNC(get_thd(), "mdl_after_find_deadlock");
|
||||
|
||||
struct timespec abs_timeout, abs_shortwait;
|
||||
set_timespec_nsec(abs_timeout,
|
||||
(ulonglong)(lock_wait_timeout * 1000000000ULL));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user