summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkevin.lewis@oracle.com <>2013-02-27 12:44:58 -0600
committerkevin.lewis@oracle.com <>2013-02-27 12:44:58 -0600
commitaeb9e7d8146e286b0d68f80dda0d5d3893ab9f86 (patch)
treece7f65b2d3bbf6b19160920e051ff288d35bbd94
parent39d39c3bc2831bb6c14ed8ad07c9454eb4d47f53 (diff)
downloadmariadb-git-aeb9e7d8146e286b0d68f80dda0d5d3893ab9f86.tar.gz
Bug #16305265 HANG IN RENAME TABLE
This is a deadlock that will also be fixed in the server by Bug #11844915 - HANG IN THDVAR MUTEX ACQUISITION. So this is a simple alternate method of fixing the same problem, but from within InnoDB. The simple change is to make rename table start a transaction before locking dict_sys->mutex since thd_supports_xa() can call THDVAR which can lock a mutex, LOCK_global_system_variables, that is used in the server by many other activities. At least one of those, sys_var::update(), can call back into InnoDB and try to lock dict_sys->mutex while holding LOCK_global_system_variables. The other bug fix for 11844915 eliminates the use of LOCK_global_system_variables for calls to THDVAR. Approved by marko in http://rb.no.oracle.com/rb/r/2000/
-rw-r--r--storage/innobase/handler/ha_innodb.cc8
-rw-r--r--storage/innobase/row/row0mysql.c2
2 files changed, 8 insertions, 2 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 65d6726b5bf..997fdb6244c 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7599,12 +7599,18 @@ innobase_rename_table(
DEBUG_SYNC_C("innodb_rename_table_ready");
/* Serialize data dictionary operations with dictionary mutex:
- no deadlocks can occur then in these operations */
+ no deadlocks can occur then in these operations. Start the
+ transaction first to avoid a possible deadlock in the server. */
+ trx_start_if_not_started(trx);
if (lock_and_commit) {
row_mysql_lock_data_dictionary(trx);
}
+ /* Flag this transaction as a dictionary operation, so that
+ the data dictionary will be locked in crash recovery. */
+ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+
error = row_rename_table_for_mysql(
norm_from, norm_to, trx, lock_and_commit);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 73da6215f0d..77fa6518b35 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -3840,6 +3840,7 @@ row_rename_table_for_mysql(
ut_a(old_name != NULL);
ut_a(new_name != NULL);
+ ut_ad(trx->conc_state == TRX_ACTIVE);
if (srv_created_new_raw || srv_force_recovery) {
fputs("InnoDB: A new raw disk partition was initialized or\n"
@@ -3864,7 +3865,6 @@ row_rename_table_for_mysql(
}
trx->op_info = "renaming table";
- trx_start_if_not_started(trx);
old_is_tmp = row_is_mysql_tmp_table_name(old_name);
new_is_tmp = row_is_mysql_tmp_table_name(new_name);