diff options
author | kevin.lewis@oracle.com <> | 2013-02-27 12:44:58 -0600 |
---|---|---|
committer | kevin.lewis@oracle.com <> | 2013-02-27 12:44:58 -0600 |
commit | aeb9e7d8146e286b0d68f80dda0d5d3893ab9f86 (patch) | |
tree | ce7f65b2d3bbf6b19160920e051ff288d35bbd94 | |
parent | 39d39c3bc2831bb6c14ed8ad07c9454eb4d47f53 (diff) | |
download | mariadb-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.cc | 8 | ||||
-rw-r--r-- | 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); |