summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2020-11-30 15:29:32 +0200
committerMonty <monty@mariadb.org>2020-11-30 22:21:43 +0200
commit828471cbf83774f4537a78551290b7a4a7f5d374 (patch)
treeef6dee7179466f556d64cd1e9d76038cc6bf3ddc
parent37352c4b554a46895cd725ab17c9397724a43757 (diff)
downloadmariadb-git-828471cbf83774f4537a78551290b7a4a7f5d374.tar.gz
MDEV 15532 Assertion `!log->same_pk' failed in row_log_table_apply_delete
The reason for the failure is that thd->mdl_context.release_transactional_locks() was called after commit & rollback even in cases where the current transaction is still active. For 10.2, 10.3 and 10.4 the fix is simple: - Replace all calls to thd->mdl_context.release_transactional_locks() with thd->release_transactional_locks(). The thd function will only call the mdl_context function if there are no active transactional locks. In 10.6 we will better fix where we will change the return value for some trans_xxx() functions to indicate if transaction did close the transaction or not. This will avoid the need of the indirect call. Other things: - trans_xa_commit() and trans_xa_rollback() will automatically call release_transactional_locks() if the transaction is closed. - We can't do that for the other functions as the caller of many of these are doing additional work (like close_thread_tables) before calling release_transactional_locks(). - Added missing abort_result_set() and missing DBUG_RETURN in select_create::send_eof() - Fixed wrong indentation in injector::transaction::commit()
-rw-r--r--mysql-test/r/xa.result28
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result1
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test1
-rw-r--r--mysql-test/t/xa.test44
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/mdl.cc3
-rw-r--r--sql/rpl_gtid.cc4
-rw-r--r--sql/rpl_injector.cc56
-rw-r--r--sql/rpl_rli.cc8
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sql_admin.cc20
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_insert.cc7
-rw-r--r--sql/sql_parse.cc30
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sys_vars.cc2
-rw-r--r--sql/transaction.cc7
-rw-r--r--sql/wsrep_applier.cc4
-rw-r--r--sql/wsrep_thd.cc6
21 files changed, 164 insertions, 84 deletions
diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result
index 6ae4a06399c..8ff84862270 100644
--- a/mysql-test/r/xa.result
+++ b/mysql-test/r/xa.result
@@ -241,7 +241,7 @@ DROP TABLE t1;
#
# Bug#12352846 - TRANS_XA_START(THD*):
# ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
-# FAILED
+# FAILED
#
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
@@ -291,3 +291,29 @@ connection default;
XA END 'xid1';
XA ROLLBACK 'xid1';
DROP TABLE t1, t2, t3;
+#
+# MDEV 15532 XA: Assertion `!log->same_pk' failed in
+# row_log_table_apply_delete
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+connect con1,localhost,root,,test;
+XA START 'xid';
+UPDATE t1 SET a = 5;
+connection default;
+SET innodb_lock_wait_timeout= 2, lock_wait_timeout= 2;
+ALTER TABLE non_existing_table1;
+ERROR 42S02: Table 'test.non_existing_table1' doesn't exist
+ALTER TABLE t1 FORCE;;
+connection con1;
+ALTER TABLE non_existing_table2;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
+DELETE FROM t1 LIMIT 1;
+connection default;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+connection con1;
+XA END 'xid';
+XA ROLLBACK 'xid';
+DROP TABLE t1;
+disconnect con1;
+connection default;
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index 8101ae6bea2..ca27595ffa0 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -413,6 +413,7 @@ CREATE TABLE x AS SELECT * FROM t1;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
connect con1,localhost,root,,test;
SET foreign_key_checks= OFF, innodb_lock_wait_timeout= 1;
+SET lock_wait_timeout=5;
ALTER TABLE t1 ADD FOREIGN KEY f (a) REFERENCES t1 (pk), LOCK=EXCLUSIVE;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
disconnect con1;
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 380d4520d87..7756d48046f 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -414,6 +414,7 @@ INSERT INTO t1 VALUES (1,2);
CREATE TABLE x AS SELECT * FROM t1;
--connect (con1,localhost,root,,test)
SET foreign_key_checks= OFF, innodb_lock_wait_timeout= 1;
+SET lock_wait_timeout=5;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE t1 ADD FOREIGN KEY f (a) REFERENCES t1 (pk), LOCK=EXCLUSIVE;# Cleanup
--disconnect con1
diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test
index 58ad1caaeef..ecce563b8c8 100644
--- a/mysql-test/t/xa.test
+++ b/mysql-test/t/xa.test
@@ -342,7 +342,7 @@ DROP TABLE t1;
--echo #
--echo # Bug#12352846 - TRANS_XA_START(THD*):
--echo # ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
---echo # FAILED
+--echo # FAILED
--echo #
--disable_warnings
@@ -401,7 +401,7 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (pk INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t2 VALUES (1),(2);
CREATE TABLE t3 (i INT) ENGINE=InnoDB;
-
+
XA BEGIN 'xid1';
REPLACE INTO t1 SELECT * FROM t2;
@@ -430,5 +430,43 @@ XA END 'xid1';
XA ROLLBACK 'xid1';
DROP TABLE t1, t2, t3;
---source include/wait_until_count_sessions.inc
+--echo #
+--echo # MDEV 15532 XA: Assertion `!log->same_pk' failed in
+--echo # row_log_table_apply_delete
+--echo #
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+
+--connect (con1,localhost,root,,test)
+
+XA START 'xid';
+UPDATE t1 SET a = 5;
+
+--connection default
+SET innodb_lock_wait_timeout= 2, lock_wait_timeout= 2;
+
+--error ER_NO_SUCH_TABLE
+ALTER TABLE non_existing_table1;
+
+--send ALTER TABLE t1 FORCE;
+--connection con1
+--error ER_XAER_RMFAIL
+
+ALTER TABLE non_existing_table2;
+DELETE FROM t1 LIMIT 1;
+
+--connection default
+--error ER_LOCK_WAIT_TIMEOUT
+--reap
+
+# Cleanup
+--connection con1
+XA END 'xid';
+XA ROLLBACK 'xid';
+DROP TABLE t1;
+--disconnect con1
+connection default;
+
+--source include/wait_until_count_sessions.inc
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 097cbe8da9d..c649e1f64fa 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7150,10 +7150,10 @@ error:
if (thd->transaction_rollback_request)
{
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_multi_stmt_transaction_mode())
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
else
thd->mdl_context.release_statement_locks();
@@ -8554,7 +8554,7 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi)
"COMMIT /* implicit, from Xid_log_event */");
thd->variables.option_bits&= ~OPTION_GTID_BEGIN;
res= trans_commit(thd); /* Automatically rolls back on error. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
#ifdef WITH_WSREP
if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 9eeb82eeffd..f2b205a86f2 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -2842,6 +2842,9 @@ void MDL_context::rollback_to_savepoint(const MDL_savepoint &mdl_savepoint)
void MDL_context::release_transactional_locks()
{
DBUG_ENTER("MDL_context::release_transactional_locks");
+ /* Fail if there are active transactions */
+ DBUG_ASSERT(!(current_thd->server_status &
+ (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY)));
release_locks_stored_before(MDL_STATEMENT, NULL);
release_locks_stored_before(MDL_TRANSACTION, NULL);
DBUG_VOID_RETURN;
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 43fdeec9e6a..a8f7641fce4 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -432,7 +432,7 @@ rpl_slave_state::truncate_state_table(THD *thd)
close_thread_tables(thd);
ha_commit_trans(thd, TRUE);
}
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
reenable_binlog(thd);
@@ -726,7 +726,7 @@ end:
}
else
{
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
#ifdef HAVE_REPLICATION
rpl_group_info::pending_gtid_deletes_free(elist);
#endif
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index 53999d57bf6..3bcc0204036 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -68,34 +68,34 @@ injector::transaction::~transaction()
*/
int injector::transaction::commit()
{
- DBUG_ENTER("injector::transaction::commit()");
- int error= m_thd->binlog_flush_pending_rows_event(true);
- /*
- Cluster replication does not preserve statement or
- transaction boundaries of the master. Instead, a new
- transaction on replication slave is started when a new GCI
- (global checkpoint identifier) is issued, and is committed
- when the last event of the check point has been received and
- processed. This ensures consistency of each cluster in
- cluster replication, and there is no requirement for stronger
- consistency: MySQL replication is asynchronous with other
- engines as well.
-
- A practical consequence of that is that row level replication
- stream passed through the injector thread never contains
- COMMIT events.
- Here we should preserve the server invariant that there is no
- outstanding statement transaction when the normal transaction
- is committed by committing the statement transaction
- explicitly.
- */
- trans_commit_stmt(m_thd);
- if (!trans_commit(m_thd))
- {
- close_thread_tables(m_thd);
- m_thd->mdl_context.release_transactional_locks();
- }
- DBUG_RETURN(error);
+ DBUG_ENTER("injector::transaction::commit()");
+ int error= m_thd->binlog_flush_pending_rows_event(true);
+ /*
+ Cluster replication does not preserve statement or
+ transaction boundaries of the master. Instead, a new
+ transaction on replication slave is started when a new GCI
+ (global checkpoint identifier) is issued, and is committed
+ when the last event of the check point has been received and
+ processed. This ensures consistency of each cluster in
+ cluster replication, and there is no requirement for stronger
+ consistency: MySQL replication is asynchronous with other
+ engines as well.
+
+ A practical consequence of that is that row level replication
+ stream passed through the injector thread never contains
+ COMMIT events.
+ Here we should preserve the server invariant that there is no
+ outstanding statement transaction when the normal transaction
+ is committed by committing the statement transaction
+ explicitly.
+ */
+ trans_commit_stmt(m_thd);
+ if (!trans_commit(m_thd))
+ {
+ close_thread_tables(m_thd);
+ m_thd->release_transactional_locks();
+ }
+ DBUG_RETURN(error);
}
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index d2d1bc3421d..40ab375571a 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1736,7 +1736,7 @@ end:
if (table_opened)
{
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
if (array_inited)
delete_dynamic(&array);
@@ -1904,7 +1904,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
if (error)
{
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (thd == rli->sql_driver_thd)
{
@@ -2018,10 +2018,10 @@ void rpl_group_info::slave_close_thread_tables(THD *thd)
if (thd->transaction_rollback_request)
{
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_multi_stmt_transaction_mode())
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
else
thd->mdl_context.release_statement_locks();
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 6a650183fb8..b205d253733 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2163,10 +2163,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (thd->transaction_rollback_request)
{
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_multi_stmt_transaction_mode())
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
else
thd->mdl_context.release_statement_locks();
}
@@ -3119,10 +3119,10 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
if (thd->transaction_rollback_request)
{
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_multi_stmt_transaction_mode())
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
else
thd->mdl_context.release_statement_locks();
}
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index af4b9127f8f..17eede61337 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -42,7 +42,7 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
trans_rollback_stmt(thd);
trans_rollback(thd);
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/*
table_list->table has been closed and freed. Do not reference
@@ -115,7 +115,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
acquire the exclusive lock to satisfy MDL asserts and avoid
deadlocks.
*/
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/*
Attempt to do full-blown table open in mysql_admin_table() has failed.
Let us try to open at least a .FRM for this table.
@@ -266,7 +266,7 @@ end:
}
/* In case of a temporary table there will be no metadata lock. */
if (error && has_mdl_lock)
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
DBUG_RETURN(error);
}
@@ -543,7 +543,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
trans_rollback(thd);
close_thread_tables(thd);
table->table= NULL;
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
}
@@ -597,7 +597,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
trans_rollback_stmt(thd);
trans_rollback(thd);
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
DBUG_PRINT("admin", ("simple error, admin next table"));
continue;
case -1: // error, message could be written to net
@@ -670,7 +670,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
lex->reset_query_tables_list(FALSE);
/*
Restore Query_tables_list::sql_command value to make statement
@@ -803,7 +803,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->open_options|= extra_open_options;
close_thread_tables(thd);
table->table= NULL;
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
table->mdl_request.set_type(MDL_SHARED_READ);
@@ -1035,7 +1035,7 @@ send_result_message:
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/* Clear references to TABLE and MDL_ticket after releasing them. */
table->mdl_request.ticket= NULL;
@@ -1188,7 +1188,7 @@ send_result_message:
goto err;
}
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/*
If it is CHECK TABLE v1, v2, v3, and v1, v2, v3 are views, we will run
@@ -1226,7 +1226,7 @@ err:
table->table= 0;
}
close_thread_tables(thd); // Shouldn't be needed
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->resume_subsequent_commits(suspended_wfc);
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 635e17d1865..590073bbed7 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8652,7 +8652,7 @@ close_mysql_tables(THD *thd)
if (! thd->in_sub_stmt)
trans_commit_stmt(thd);
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 488424d5da5..7eaafbd9044 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4485,7 +4485,7 @@ void destroy_thd(MYSQL_THD thd)
void reset_thd(MYSQL_THD thd)
{
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->free_items();
free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2727b4c84d5..84f188b7803 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4177,6 +4177,13 @@ public:
locked_tables_mode= mode_arg;
}
void leave_locked_tables_mode();
+ /* Relesae transactional locks if there are no active transactions */
+ void release_transactional_locks()
+ {
+ if (!(server_status &
+ (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY)))
+ mdl_context.release_transactional_locks();
+ }
int decide_logging_format(TABLE_LIST *tables);
/*
In Some cases when decide_logging_format is called it does not have all
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0c50a251d26..ec79ff6d688 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2948,7 +2948,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (thd->mdl_context.clone_ticket(&di->grl_protection) ||
thd->mdl_context.clone_ticket(&di->table_list.mdl_request))
{
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
di->handler_thread_initialized= TRUE;
goto err;
}
@@ -3144,7 +3144,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
mysql_mutex_unlock(&thd->LOCK_thd_data);
close_thread_tables(thd); // Free the table
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
mysql_cond_broadcast(&di->cond_client); // Safety
mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table
@@ -4580,7 +4580,8 @@ bool select_create::send_eof()
WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
(wsrep_thd_query(thd)) ?
wsrep_thd_query(thd) : "void", rcode);
- return true;
+ abort_result_set();
+ DBUG_RETURN(true);
}
/* If commit fails, we should be able to reset the OK status. */
thd->get_stmt_da()->set_overwrite_status(TRUE);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 83100e743ad..0166c4554e7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2034,7 +2034,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
locks.
*/
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
thd->cleanup_after_query();
@@ -2099,7 +2099,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ulonglong options= (ulonglong) (uchar) packet[0];
if (trans_commit_implicit(thd))
break;
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (check_global_access(thd,RELOAD_ACL))
break;
general_log_print(thd, command, NullS);
@@ -2132,7 +2132,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (trans_commit_implicit(thd))
break;
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
my_ok(thd);
break;
}
@@ -2934,7 +2934,7 @@ err:
/* Close tables and release metadata locks. */
close_thread_tables(thd);
DBUG_ASSERT(!thd->locked_tables_mode);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
return TRUE;
}
@@ -3406,7 +3406,7 @@ mysql_execute_command(THD *thd)
/* Commit the normal transaction if one is active. */
bool commit_failed= trans_commit_implicit(thd);
/* Release metadata locks acquired in this transaction. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("implicit commit failed, MDL released: %lld",
@@ -4645,7 +4645,7 @@ mysql_execute_command(THD *thd)
{
res= trans_commit_implicit(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock.is_acquired())
@@ -4659,7 +4659,7 @@ mysql_execute_command(THD *thd)
res= trans_commit_implicit(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
/* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (res)
goto error;
@@ -5313,7 +5313,7 @@ mysql_execute_command(THD *thd)
DBUG_PRINT("info", ("Executing SQLCOM_BEGIN thd: %p", thd));
if (trans_begin(thd, lex->start_transaction_opt))
{
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
WSREP_DEBUG("BEGIN failed, MDL released: %lld",
(longlong) thd->thread_id);
goto error;
@@ -5331,7 +5331,7 @@ mysql_execute_command(THD *thd)
(thd->variables.completion_type == 2 &&
lex->tx_release != TVL_NO));
bool commit_failed= trans_commit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("COMMIT failed, MDL released: %lld",
@@ -5382,7 +5382,7 @@ mysql_execute_command(THD *thd)
(thd->variables.completion_type == 2 &&
lex->tx_release != TVL_NO));
bool rollback_failed= trans_rollback(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (rollback_failed)
{
@@ -5859,7 +5859,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_XA_COMMIT:
{
bool commit_failed= trans_xa_commit(thd);
- thd->mdl_context.release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("XA commit failed, MDL released: %lld",
@@ -5877,7 +5876,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_XA_ROLLBACK:
{
bool rollback_failed= trans_xa_rollback(thd);
- thd->mdl_context.release_transactional_locks();
if (rollback_failed)
{
WSREP_DEBUG("XA rollback failed, MDL released: %lld",
@@ -6095,7 +6093,7 @@ finish:
all storage engines including binary log.
*/
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
{
@@ -6108,7 +6106,7 @@ finish:
/* Commit the normal transaction if one is active. */
trans_commit_implicit(thd);
thd->get_stmt_da()->set_overwrite_status(false);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
}
else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode())
@@ -6123,7 +6121,7 @@ finish:
- If in autocommit mode, or outside a transactional context,
automatically release metadata locks of the current statement.
*/
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_sub_stmt)
{
@@ -6145,7 +6143,7 @@ finish:
{
WSREP_DEBUG("Forcing release of transactional locks for thd: %lld",
(longlong) thd->thread_id);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
#endif /* WITH_WSREP */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4bf8142959d..3144b36ff77 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4278,7 +4278,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
if (thd->transaction_rollback_request)
{
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
/* Preserve CHANGE MASTER attributes */
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 2a582a098fb..7b74689a7f0 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3730,7 +3730,7 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type)
if (trans_commit_stmt(thd) || trans_commit(thd))
{
thd->variables.option_bits&= ~OPTION_AUTOCOMMIT;
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
WSREP_DEBUG("autocommit, MDL TRX lock released: %lld",
(longlong) thd->thread_id);
return true;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 72b7f8e6fe4..543e0b7ad38 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -212,7 +212,7 @@ bool trans_begin(THD *thd, uint flags)
Release transactional metadata locks only after the
transaction has been committed.
*/
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
// The RO/RW options are mutually exclusive.
DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) &&
@@ -889,11 +889,13 @@ bool trans_xa_prepare(THD *thd)
/**
Commit and terminate the a XA transaction.
+ Transactional locks are released if transaction ended
@param thd Current thread
@retval FALSE Success
@retval TRUE Failure
+
*/
bool trans_xa_commit(THD *thd)
@@ -984,6 +986,7 @@ bool trans_xa_commit(THD *thd)
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
+ thd->mdl_context.release_transactional_locks();
DBUG_RETURN(res);
}
@@ -991,6 +994,7 @@ bool trans_xa_commit(THD *thd)
/**
Roll back and terminate a XA transaction.
+ Transactional locks are released if transaction ended
@param thd Current thread
@@ -1041,6 +1045,7 @@ bool trans_xa_rollback(THD *thd)
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
+ thd->mdl_context.release_transactional_locks();
DBUG_RETURN(res);
}
diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc
index 66335c412e2..ea8ebb7522f 100644
--- a/sql/wsrep_applier.cc
+++ b/sql/wsrep_applier.cc
@@ -187,7 +187,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
trans_rollback(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
/* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->wsrep_conflict_state= NO_CONFLICT;
DBUG_RETURN(WSREP_CB_FAILURE);
}
@@ -369,7 +369,7 @@ wsrep_cb_status_t wsrep_commit_cb(void* const ctx,
/* Cleanup */
wsrep_set_apply_format(thd, NULL);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->reset_query(); /* Mutex protected */
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index 4dddb399bd1..2396b8663df 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -75,7 +75,7 @@ void wsrep_client_rollback(THD *thd)
}
/* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/* release explicit MDL locks */
thd->mdl_context.release_explicit_locks();
@@ -211,7 +211,7 @@ void wsrep_replay_sp_transaction(THD* thd)
thd->locked_tables_list.unlock_locked_tables(thd);
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
mysql_mutex_unlock(&thd->LOCK_thd_data);
THD *replay_thd= new THD(true);
@@ -350,7 +350,7 @@ void wsrep_replay_transaction(THD *thd)
thd->locked_tables_list.unlock_locked_tables(thd);
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
/*
Replaying will call MYSQL_START_STATEMENT when handling
BEGIN Query_log_event so end statement must be called before