Skip to content

Commit bfbba94

Browse files
committed
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() (from 92bfc0e) 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() (from 92bfc0e) 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: 92bfc0e MDEV-17554, assert added f885116 MDEV-28567, test added, assertion modified fe3adde MDEV-29060, test moved, fix attempted 8ee93b9 MDEV-29060, fix attempted 611d442 fix attempted 77c465d assertion modified 4c695c8 assertion removed MDEV-29474 - subj MDEV-36665 - duplicate of MDEV-29474
1 parent 060c0e3 commit bfbba94

File tree

5 files changed

+85
-145
lines changed

5 files changed

+85
-145
lines changed

mysql-test/main/lock_sync.result

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -856,28 +856,3 @@ SET DEBUG_SYNC="RESET";
856856
disconnect con1;
857857
disconnect con2;
858858
DROP TABLES t1, t2;
859-
#
860-
# MDEV-28567 Assertion `0' in open_tables upon function-related operation
861-
#
862-
CREATE TABLE t1 (a INT);
863-
CREATE TABLE t2 (b INT);
864-
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW UPDATE t2 SET b = 0;
865-
CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW UPDATE t1 SET a = 6;
866-
CREATE VIEW v1 AS SELECT * FROM t1;
867-
SET AUTOCOMMIT=OFF;
868-
SELECT * FROM t1;
869-
a
870-
DROP TRIGGER tr1;
871-
INSERT INTO t2 SELECT * FROM t2;
872-
SELECT f() FROM t2;
873-
ERROR 42000: FUNCTION test.f does not exist
874-
set debug_sync= 'after_open_table_mdl_shared signal s1';
875-
ALTER VIEW v1 AS SELECT f() FROM t1;
876-
CREATE FUNCTION f() RETURNS INT RETURN 1;
877-
set debug_sync= 'now wait_for s1';
878-
SELECT * FROM ( SELECT * FROM v1 ) sq;
879-
COMMIT;
880-
DROP VIEW v1;
881-
DROP FUNCTION IF EXISTS f;
882-
DROP TABLE t1, t2;
883-
set debug_sync= 'reset';

mysql-test/main/lock_sync.test

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,123 +1079,3 @@ DROP TABLES t1, t2;
10791079
# Check that all connections opened by test cases in this file are really
10801080
# gone so execution of other tests won't be affected by their presence.
10811081
--source include/wait_until_count_sessions.inc
1082-
1083-
--echo #
1084-
--echo # MDEV-28567 Assertion `0' in open_tables upon function-related operation
1085-
--echo #
1086-
# To get MDL trace run this case like this:
1087-
# mtr --mysqld=--debug=d,mdl,query:i:o,/tmp/mdl.log ...
1088-
# Cleanup trace like this:
1089-
# sed -i -re '/(mysql|performance_schema|sys|mtr)\// d; /MDL_BACKUP_|MDL_INTENTION_/ d; /\/(t2|tr1|tr2)/ d' /tmp/mdl.log
1090-
1091-
CREATE TABLE t1 (a INT);
1092-
CREATE TABLE t2 (b INT);
1093-
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW UPDATE t2 SET b = 0;
1094-
CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW UPDATE t1 SET a = 6;
1095-
CREATE VIEW v1 AS SELECT * FROM t1;
1096-
1097-
SET AUTOCOMMIT=OFF;
1098-
SELECT * FROM t1;
1099-
# T@6
1100-
# Seized: test/t1 (MDL_SHARED_READ)
1101-
1102-
--connect (con1,localhost,root,,test)
1103-
--send
1104-
DROP TRIGGER tr1;
1105-
# T@7
1106-
# Seized: test/t1 (MDL_SHARED_NO_WRITE)
1107-
# Waiting: test/t1 (MDL_EXCLUSIVE)
1108-
# Waiting: test/t1 (MDL_SHARED_WRITE)
1109-
# Deadlock: test/t1 (MDL_SHARED_WRITE)
1110-
1111-
--connection default
1112-
--error 0, ER_LOCK_DEADLOCK
1113-
INSERT INTO t2 SELECT * FROM t2;
1114-
# T@6
1115-
# Released: test/t1 (MDL_SHARED_READ)
1116-
# T@7
1117-
# Acquired: test/t1 (MDL_EXCLUSIVE) (good)
1118-
--error ER_SP_DOES_NOT_EXIST
1119-
SELECT f() FROM t2;
1120-
# T@6
1121-
# Seized: test/f (MDL_SHARED)
1122-
# T@7
1123-
# Released: test/t1 (MDL_EXCLUSIVE)
1124-
# Good1: continue T@6 below
1125-
# Bad1: continue T@8 below
1126-
1127-
# Now we hold test/f, the below code creates concurrent
1128-
# waiting of 3 threads for test/f which leads to deadlock (Bad)
1129-
1130-
# To achive Good comment out 'now wait_for s1' below and run multiple times.
1131-
1132-
--connect (con2,localhost,root,,test)
1133-
set debug_sync= 'after_open_table_mdl_shared signal s1';
1134-
--send
1135-
ALTER VIEW v1 AS SELECT f() FROM t1;
1136-
# T@8
1137-
# Good2: Waiting: test/v1 (MDL_EXCLUSIVE)
1138-
# Good2-3: continue T@7 below
1139-
# Good5: Acquired: test/v1 (MDL_EXCLUSIVE)
1140-
# Good5: Seized: test/v1 (MDL_EXCLUSIVE)
1141-
# Good5-6: continue T@7 below
1142-
# Good7: Seized: test/t1 (MDL_SHARED_READ)
1143-
# Good7: Waiting: test/f (MDL_SHARED)
1144-
# Good7-8: continue T@7 below
1145-
# Good9: Acquired: test/f (MDL_SHARED)
1146-
# Good9: Released: test/f (MDL_SHARED)
1147-
# Good9: Released: test/t1 (MDL_SHARED_READ)
1148-
# Good9: Released: test/v1 (MDL_EXCLUSIVE)
1149-
# Good9: command finished without error
1150-
# Bad1: Seized: test/v1 (MDL_EXCLUSIVE)
1151-
# Bad1: Seized: test/v1 (MDL_EXCLUSIVE)
1152-
# Bad1: Seized: test/t1 (MDL_SHARED_READ)
1153-
# Bad1-2: continue T@6 below
1154-
# Bad4: Waiting: test/f (MDL_SHARED)
1155-
# Bad4: Deadlock: test/f (MDL_SHARED)
1156-
# Bad4: command finished with error
1157-
1158-
--connection con1
1159-
--reap
1160-
--send
1161-
CREATE FUNCTION f() RETURNS INT RETURN 1;
1162-
# T@7
1163-
# Good3: Waiting: test/f (MDL_EXCLUSIVE)
1164-
# Good3-4: continue T@6 below
1165-
# Good6: Acquired: test/f (MDL_EXCLUSIVE)
1166-
# Good6-7: continue T@8 above
1167-
# Good8: Released: test/f (MDL_EXCLUSIVE)
1168-
# Good8-9: continue T@8 above
1169-
# Bad3: Waiting: test/f (MDL_EXCLUSIVE)
1170-
# Bad3-4: continue T@8 above
1171-
1172-
--connection default
1173-
set debug_sync= 'now wait_for s1';
1174-
--disable_result_log
1175-
SELECT * FROM ( SELECT * FROM v1 ) sq;
1176-
--enable_result_log
1177-
# T@6
1178-
# Good1: Seized: test/v1 (MDL_SHARED_READ)
1179-
# Good1-2: continue T@8 above
1180-
# Good4: Seized: test/t1 (MDL_SHARED_READ)
1181-
# Bad2: Waiting: test/v1 (MDL_SHARED_READ)
1182-
# Bad2-3: continue T@7 above
1183-
1184-
# Cleanup
1185-
COMMIT;
1186-
# Good4: Released: test/t1 (MDL_SHARED_READ)
1187-
# Good4: Released: test/v1 (MDL_SHARED_READ)
1188-
# Good4: Released: test/f (MDL_SHARED)
1189-
# Good4-5: continue T@8 above
1190-
1191-
--connection con2
1192-
--error 0, ER_SP_DOES_NOT_EXIST
1193-
--reap
1194-
--disconnect con1
1195-
--disconnect con2
1196-
--connection default
1197-
--source include/wait_until_count_sessions.inc
1198-
DROP VIEW v1;
1199-
DROP FUNCTION IF EXISTS f;
1200-
DROP TABLE t1, t2;
1201-
set debug_sync= 'reset';

mysql-test/main/mdl_sync.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,3 +3015,34 @@ connection default;
30153015
SET debug_sync='RESET';
30163016
DROP TABLE t1;
30173017
disconnect con1;
3018+
#
3019+
# MDEV-28567 Assertion `0' in open_tables upon function-related operation
3020+
#
3021+
CREATE VIEW v1 AS SELECT 1;
3022+
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
3023+
connect con1, localhost, root;
3024+
SET debug_sync='open_and_process_table SIGNAL ready1 WAIT_FOR go1';
3025+
ALTER VIEW v1 AS SELECT f1();
3026+
connect con2, localhost, root;
3027+
SET debug_sync='now WAIT_FOR ready1';
3028+
SET debug_sync='mdl_after_find_deadlock SIGNAL ready2';
3029+
SELECT f1();
3030+
connect con3, localhost, root;
3031+
SET debug_sync='now WAIT_FOR ready2';
3032+
SET debug_sync='mdl_after_find_deadlock SIGNAL ready3';
3033+
DROP FUNCTION f1;
3034+
connection default;
3035+
SET debug_sync='now WAIT_FOR ready3';
3036+
SET debug_sync='now SIGNAL go1';
3037+
connection con3;
3038+
disconnect con3;
3039+
connection con2;
3040+
f1()
3041+
1
3042+
disconnect con2;
3043+
connection con1;
3044+
ERROR 42000: FUNCTION test.f1 does not exist
3045+
disconnect con1;
3046+
connection default;
3047+
DROP VIEW v1;
3048+
SET debug_sync='reset';

mysql-test/main/mdl_sync.test

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,6 +4010,58 @@ DROP TABLE t1;
40104010

40114011
disconnect con1;
40124012

4013+
4014+
--echo #
4015+
--echo # MDEV-28567 Assertion `0' in open_tables upon function-related operation
4016+
--echo #
4017+
#
4018+
# This test covers deadlock recovery code in open_tables() after
4019+
# open_and_process_routine(). ALTER VIEW v1 connection must fall as a deadlock
4020+
# victim to hit this code.
4021+
#
4022+
# default connection cannot be used since it may have deadlock weight spoiled
4023+
# by "MDL deadlock overweight" feature from previous deadlocks. In this case
4024+
# ALTER VIEW v1 won't fall as a deadlock victim and the test won't cover
4025+
# intended code.
4026+
#
4027+
CREATE VIEW v1 AS SELECT 1;
4028+
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
4029+
4030+
connect con1, localhost, root;
4031+
SET debug_sync='open_and_process_table SIGNAL ready1 WAIT_FOR go1';
4032+
send ALTER VIEW v1 AS SELECT f1(); # X v1, S f1
4033+
4034+
connect con2, localhost, root;
4035+
SET debug_sync='now WAIT_FOR ready1';
4036+
SET debug_sync='mdl_after_find_deadlock SIGNAL ready2';
4037+
send SELECT f1(); # S f1, SR v1
4038+
4039+
connect con3, localhost, root;
4040+
SET debug_sync='now WAIT_FOR ready2';
4041+
SET debug_sync='mdl_after_find_deadlock SIGNAL ready3';
4042+
send DROP FUNCTION f1; # X f1
4043+
4044+
connection default;
4045+
SET debug_sync='now WAIT_FOR ready3';
4046+
SET debug_sync='now SIGNAL go1';
4047+
4048+
connection con3;
4049+
reap;
4050+
disconnect con3;
4051+
4052+
connection con2;
4053+
reap;
4054+
disconnect con2;
4055+
4056+
connection con1;
4057+
--error ER_SP_DOES_NOT_EXIST
4058+
reap;
4059+
disconnect con1;
4060+
4061+
connection default;
4062+
DROP VIEW v1;
4063+
SET debug_sync='reset';
4064+
40134065
# Check that all connections opened by test cases in this file are really
40144066
# gone so execution of other tests won't be affected by their presence.
40154067
--source include/wait_until_count_sessions.inc

sql/mdl.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,8 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
23962396

23972397
find_deadlock();
23982398

2399+
DEBUG_SYNC(get_thd(), "mdl_after_find_deadlock");
2400+
23992401
struct timespec abs_timeout, abs_shortwait;
24002402
set_timespec_nsec(abs_timeout,
24012403
(ulonglong)(lock_wait_timeout * 1000000000ULL));

0 commit comments

Comments
 (0)