summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/mdl_sync.result48
-rw-r--r--mysql-test/t/mdl_sync.test103
-rw-r--r--sql/mdl.h2
-rw-r--r--sql/sql_base.cc4
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;
}