From e1e43631f86828b90e4f80eb1b76501676ff565f Mon Sep 17 00:00:00 2001 From: unknown <kevin.lewis@oracle.com> Date: Wed, 27 Feb 2013 12:44:58 -0600 Subject: [PATCH] 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/ --- storage/innobase/handler/ha_innodb.cc | 8 +++++++- storage/innobase/row/row0mysql.c | 2 +- 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); -- 2.30.9