MDEV-28399 Assertion failure in dict_table_check_for_dup_indexes upon concurrent DML/DDL

Problem:
========
 InnoDB DDL fails to remove the newly added table or index from
dictionary and index stub from the table cache if the alter
transaction encounters DEADLOCK error in commit phase.

Solution:
========
Restart the alter table transaction if it encounters DEADLOCK
in commit phase. So that index stubs and index, table removal from
dictionary can be done in rollback_inplace_alter_table()

- Added one assert in rollback_inplace_alter_table() to indicate that
the online log for the old table shouldn't exist.
parent a42e327a
......@@ -134,7 +134,7 @@ DROP TABLE t1;
#
CREATE TABLE t1(a INT PRIMARY KEY, b INT, INDEX(b)) ENGINE=InnoDB;
SET @save_dbug=@@debug_dbug;
SET debug_dbug='+d,innodb_table_deadlock';
SET debug_dbug='+d,deadlock_table_fail';
ALTER TABLE t1 DROP INDEX b, ALGORITHM=INPLACE;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SET debug_dbug=@save_dbug;
......
......@@ -180,7 +180,7 @@ DROP TABLE t1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT, INDEX(b)) ENGINE=InnoDB;
SET @save_dbug=@@debug_dbug;
SET debug_dbug='+d,innodb_table_deadlock';
SET debug_dbug='+d,deadlock_table_fail';
--error ER_LOCK_DEADLOCK
ALTER TABLE t1 DROP INDEX b, ALGORITHM=INPLACE;
SET debug_dbug=@save_dbug;
......
......@@ -8884,6 +8884,7 @@ inline bool rollback_inplace_alter_table(Alter_inplace_info *ha_alter_info,
}
}
DBUG_ASSERT(!prebuilt->table->indexes.start->online_log);
DBUG_ASSERT(prebuilt->table->indexes.start->online_status ==
ONLINE_INDEX_COMPLETE);
......@@ -10938,6 +10939,12 @@ ha_innobase::commit_inplace_alter_table(
LOCK_X);
}
DBUG_EXECUTE_IF("deadlock_table_fail",
{
error= DB_DEADLOCK;
trx_rollback_for_mysql(trx);
});
if (error != DB_SUCCESS) {
lock_fail:
my_error_innodb(
......@@ -10945,6 +10952,16 @@ ha_innobase::commit_inplace_alter_table(
if (fts_exist) {
purge_sys.resume_FTS();
}
/* Deadlock encountered and rollbacked the
transaction. So restart the transaction
to remove the newly created table or
index from data dictionary and table cache
in rollback_inplace_alter_table() */
if (trx->state == TRX_STATE_NOT_STARTED) {
trx_start_for_ddl(trx);
}
DBUG_RETURN(true);
} else if ((ctx->new_table->flags2
& (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment