Skip to content

Commit cf3e608

Browse files
Aakanksha VermaHery Ramilison
Aakanksha Verma
authored and
Hery Ramilison
committed
Bug #27212129 [ERROR] INNODB: A RECORD LOCK WAIT HAPPENS IN A DICTIONARY
OPERATION. INDEX `ID_ PROBLEM This bug is a regression of bug#26390658. When two transactions try to do alter table partition by (and are trying to do rename table essentially),one of the transactions ends up in a lock wait trying to take a lock on record of innodb stats table as the other is holding a lock on the same record of the stats table as this transaction hasn't committed yet. A situation like this where in a transaction is made to wait for record lock of system table and is dictionary operation, innodb crashes the server.The problem is that the transaction that is done with rename table and is holding onto record locks that can be released is not able to do so because it is not yet committed .Therefore causing the lock wait and crash. FIX Solution is to let all the partitions rename to finish and commit transaction, then proceed with updating of stats table after rename. Reviewed by: bin su <[email protected]> RB: 18205 (cherry picked from commit 3b9ab1b0a3bd24151e74e73bcdfb098b969ca747)
1 parent d93b7b8 commit cf3e608

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

storage/innobase/dict/dict0stats.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,13 @@ dict_stats_rename_table(
36453645
if (ret == DB_STATS_DO_NOT_EXIST) {
36463646
ret = DB_SUCCESS;
36473647
}
3648+
DBUG_EXECUTE_IF("rename_stats",
3649+
mutex_exit(&dict_sys->mutex);
3650+
rw_lock_x_unlock(dict_operation_lock);
3651+
os_thread_sleep(20000000);
3652+
DEBUG_SYNC_C("rename_stats");
3653+
rw_lock_x_lock(dict_operation_lock);
3654+
mutex_enter(&dict_sys->mutex););
36483655

36493656
if (ret != DB_SUCCESS) {
36503657
mutex_exit(&dict_sys->mutex);

storage/innobase/row/row0mysql.cc

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Created 9/17/2000 Heikki Tuuri
3131
#include <log.h>
3232
#include <mysys_err.h>
3333
#include <sql_error.h>
34+
#include <vector>
3435

3536
#include "row0mysql.h"
3637

@@ -5327,6 +5328,7 @@ row_rename_table_for_mysql(
53275328
pars_info_add_str_literal(info, "new_table_name", new_name);
53285329
pars_info_add_str_literal(info, "old_table_name", old_name);
53295330

5331+
DEBUG_SYNC_C("rename_table");
53305332
err = que_eval_sql(info,
53315333
"PROCEDURE RENAME_TABLE () IS\n"
53325334
"BEGIN\n"
@@ -5697,6 +5699,10 @@ row_rename_partitions_for_mysql(
56975699
memcpy(from_name, old_name, from_len);
56985700
from_name[from_len] = '#';
56995701
from_name[from_len + 1] = 0;
5702+
typedef std::vector<std::pair<std::string, std::string> > partition_names;
5703+
partition_names store_name;
5704+
partition_names::iterator it;
5705+
57005706
while ((table_name = dict_get_first_table_name_in_db(from_name))) {
57015707
ut_a(memcmp(table_name, from_name, from_len) == 0);
57025708
/* Must match #[Pp]#<partition_name> */
@@ -5716,16 +5722,12 @@ row_rename_partitions_for_mysql(
57165722
error = row_rename_table_for_mysql(table_name, to_name,
57175723
trx, false);
57185724
if (error == DB_SUCCESS) {
5719-
char errstr[512];
5720-
error = dict_stats_rename_table(true, table_name, to_name,
5721-
errstr, sizeof(errstr));
5722-
if (error != DB_SUCCESS) {
5723-
ib::error() << errstr;
5724-
push_warning(thd, Sql_condition::SL_WARNING,
5725-
ER_LOCK_WAIT_TIMEOUT, errstr);
5726-
}
5727-
}
5728-
if (error != DB_SUCCESS) {
5725+
std::pair<std::string, std::string> pair_names;
5726+
pair_names.first = table_name;
5727+
pair_names.second = to_name;
5728+
store_name.push_back(pair_names);
5729+
} else {
5730+
store_name.clear();
57295731
/* Rollback and return. */
57305732
trx_rollback_for_mysql(trx);
57315733
ut_free(table_name);
@@ -5734,6 +5736,22 @@ row_rename_partitions_for_mysql(
57345736
ut_free(table_name);
57355737
}
57365738
trx_commit_for_mysql(trx);
5739+
5740+
char errstr[512];
5741+
for (it = store_name.begin(); it != store_name.end(); ++it) {
5742+
error = dict_stats_rename_table(
5743+
true, it->first.c_str(), it->second.c_str(),
5744+
errstr, sizeof(errstr));
5745+
5746+
if (error != DB_SUCCESS) {
5747+
ib::error() << errstr;
5748+
push_warning(thd, Sql_condition::SL_WARNING,
5749+
ER_LOCK_WAIT_TIMEOUT, errstr);
5750+
break;
5751+
}
5752+
}
5753+
5754+
store_name.clear();
57375755
return(error);
57385756
}
57395757

0 commit comments

Comments
 (0)