diff options
-rw-r--r-- | mysql-test/r/mdl_sync.result | 48 | ||||
-rw-r--r-- | mysql-test/t/mdl_sync.test | 103 | ||||
-rw-r--r-- | sql/mdl.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 4 |
4 files changed, 152 insertions, 5 deletions
diff --git a/mysql-test/r/mdl_sync.result b/mysql-test/r/mdl_sync.result index 8d8672377f0..79ba129ee7a 100644 --- a/mysql-test/r/mdl_sync.result +++ b/mysql-test/r/mdl_sync.result @@ -2244,3 +2244,51 @@ FLUSH TABLES WITH READ LOCK; UNLOCK TABLES; # Connection 1 SET DEBUG_SYNC= 'RESET'; +# +# Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' +# failed in open_ltable() +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (i INT); +CREATE TABLE t2 (i INT); +SET @old_general_log= @@global.general_log; +SET @@global.general_log= 1; +SET @old_log_output= @@global.log_output; +SET @@global.log_output= 'TABLE'; +SET @old_sql_log_off= @@session.sql_log_off; +SET @@session.sql_log_off= 1; +# connection: con1 +HANDLER t1 OPEN; +# connection: con3 +SET @@session.sql_log_off= 1; +# connection: con2 +SET DEBUG_SYNC= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go'; +# Sending: +SELECT 1; +# connection: con3 +SET DEBUG_SYNC= 'now WAIT_FOR parked'; +# connection: con1 +# Sending: +SELECT 1; +# connection: con3 +# Sending: +ALTER TABLE t1 ADD COLUMN j INT; +# connection: default +SET DEBUG_SYNC= 'now SIGNAL go'; +# connection: con1 +# Reaping SELECT 1 +1 +1 +HANDLER t1 CLOSE; +# connection: con2 +# Reaping SELECT 1 +1 +1 +# connection: con3 +# Reaping ALTER TABLE t1 ADD COLUMN j INT +# connection: default +DROP TABLE t1, t2; +SET DEBUG_SYNC= 'RESET'; +SET @@global.general_log= @old_general_log; +SET @@global.log_output= @old_log_output; +SET @@session.sql_log_off= @old_sql_log_off; diff --git a/mysql-test/t/mdl_sync.test b/mysql-test/t/mdl_sync.test index 0f3091794f1..4c1ffc934aa 100644 --- a/mysql-test/t/mdl_sync.test +++ b/mysql-test/t/mdl_sync.test @@ -3212,6 +3212,109 @@ SET DEBUG_SYNC= 'RESET'; disconnect con2; +--echo # +--echo # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' +--echo # failed in open_ltable() +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +connect (con1,localhost,root); +connect (con2,localhost,root); +connect (con3,localhost,root); +connection default; + +CREATE TABLE t1 (i INT); +CREATE TABLE t2 (i INT); + +SET @old_general_log= @@global.general_log; +SET @@global.general_log= 1; + +SET @old_log_output= @@global.log_output; +SET @@global.log_output= 'TABLE'; + +SET @old_sql_log_off= @@session.sql_log_off; +SET @@session.sql_log_off= 1; + +--echo # connection: con1 +connection con1; +HANDLER t1 OPEN; + +--echo # connection: con3 +connection con3; +SET @@session.sql_log_off= 1; + +--echo # connection: con2 +connection con2; +SET DEBUG_SYNC= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go'; + +# The below statement will block on the debug sync point +# after it gets write lock on mysql.general_log table. +--echo # Sending: +--send SELECT 1 + +--echo # connection: con3 +connection con3; +SET DEBUG_SYNC= 'now WAIT_FOR parked'; + +--echo # connection: con1 +connection con1; +# This statement will block in open_ltable() when +# trying to write into mysql.general_log. +--echo # Sending: +--send SELECT 1 + +--echo # connection: con3 +connection con3; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Table lock" and info = "SELECT 1"; +--source include/wait_condition.inc +# The ALTER below will try to abort the statement in connection con1, +# since the latter waits on a table-level lock while having a HANDLER +# open. This will cause mysql_lock_tables() in con1 fail which before +# triggered the assert. +--echo # Sending: +--send ALTER TABLE t1 ADD COLUMN j INT + +--echo # connection: default +connection default; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table" + AND info = "ALTER TABLE t1 ADD COLUMN j INT"; +--source include/wait_condition.inc +SET DEBUG_SYNC= 'now SIGNAL go'; + +--echo # connection: con1 +connection con1; +--echo # Reaping SELECT 1 +--reap +HANDLER t1 CLOSE; + +--echo # connection: con2 +connection con2; +--echo # Reaping SELECT 1 +--reap + +--echo # connection: con3 +connection con3; +--echo # Reaping ALTER TABLE t1 ADD COLUMN j INT +--reap + +--echo # connection: default +connection default; +DROP TABLE t1, t2; +SET DEBUG_SYNC= 'RESET'; +disconnect con1; +disconnect con2; +disconnect con3; +SET @@global.general_log= @old_general_log; +SET @@global.log_output= @old_log_output; +SET @@session.sql_log_off= @old_sql_log_off; + # 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 diff --git a/sql/mdl.h b/sql/mdl.h index 5eb86d2488b..24331cf5eac 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -540,7 +540,7 @@ public: always re-try reading it after small timeout and therefore will see the new value eventually. */ - m_needs_thr_lock_abort= TRUE; + m_needs_thr_lock_abort= needs_thr_lock_abort; } bool get_needs_thr_lock_abort() const { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e1f6d9005f5..8333f0a03c7 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4996,8 +4996,6 @@ retry: while ((error= open_table(thd, table_list, thd->mem_root, &ot_ctx, 0)) && ot_ctx.can_recover_from_failed_open()) { - /* We never have an open HANDLER, LOCK TABLES or GRL here. */ - DBUG_ASSERT(thd->mdl_context.trans_sentinel() == NULL); /* Even though we have failed to open table we still need to call release_transactional_locks() to release metadata locks which @@ -5048,8 +5046,6 @@ retry: close_thread_tables(thd); table_list->table= NULL; table_list->mdl_request.ticket= NULL; - /* We never have an open HANDLER, LOCK TABLES or GRL here. */ - DBUG_ASSERT(thd->mdl_context.trans_sentinel() == NULL); thd->mdl_context.rollback_to_savepoint(ot_ctx.start_of_statement_svp()); goto retry; } |