Skip to content
Permalink
Browse files
Merge 10.0 into 10.1
  • Loading branch information
dr-m committed May 7, 2018
2 parents b4e8ad5 + 7b9486d commit 0db66ab
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 46 deletions.
@@ -0,0 +1,15 @@
#
# MDEV-14693 XA: Assertion `!clust_index->online_log' failed
# in rollback_inplace_alter_table
#
CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB PARTITION BY HASH(a) PARTITIONS 2;
XA START 'xid';
INSERT INTO t1 VALUES (1,10);
CREATE DATABASE IF NOT EXISTS db;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
SET innodb_lock_wait_timeout= 1, lock_wait_timeout= 2;
ALTER TABLE t1 FORCE;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
XA END 'xid';
XA ROLLBACK 'xid';
DROP TABLE t1;
@@ -0,0 +1,31 @@
--source include/have_innodb.inc
--source include/have_partition.inc

--echo #
--echo # MDEV-14693 XA: Assertion `!clust_index->online_log' failed
--echo # in rollback_inplace_alter_table
--echo #

# A bug in meta-data locking (MDL) for XA transactions causes
# a bug in InnoDB error handling for ALTER TABLE to be triggered.
CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB PARTITION BY HASH(a) PARTITIONS 2;
XA START 'xid';
INSERT INTO t1 VALUES (1,10);
# XA bug: The following releases the MDL on t1!
--error ER_XAER_RMFAIL
CREATE DATABASE IF NOT EXISTS db;

--connect (con1,localhost,root,,test)
SET innodb_lock_wait_timeout= 1, lock_wait_timeout= 2;
# Here, innodb_lock_wait_timeout would be exceeded, causing the operation
# to roll back when InnoDB is attempting to commit.
# (Instead, lock_wait_timeout should be exceeded!)
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE t1 FORCE;

# Cleanup
--disconnect con1
--connection default
XA END 'xid';
XA ROLLBACK 'xid';
DROP TABLE t1;
@@ -4413,12 +4413,16 @@ rollback_inplace_alter_table(
row_mysql_lock_data_dictionary(ctx->trx);

if (ctx->need_rebuild()) {
dberr_t err;
ulint flags = ctx->new_table->flags;

/* DML threads can access ctx->new_table via the
online rebuild log. Free it first. */
innobase_online_rebuild_log_free(prebuilt->table);
}

if (!ctx->new_table) {
ut_ad(ctx->need_rebuild());
} else if (ctx->need_rebuild()) {
dberr_t err;
ulint flags = ctx->new_table->flags;

/* Since the FTS index specific auxiliary tables has
not yet registered with "table->fts" by fts_add_index(),
@@ -5786,21 +5790,6 @@ ha_innobase::commit_inplace_alter_table(
ut_ad(prebuilt->table == ctx0->old_table);
ha_alter_info->group_commit_ctx = NULL;

/* Free the ctx->trx of other partitions, if any. We will only
use the ctx0->trx here. Others may have been allocated in
the prepare stage. */

for (inplace_alter_handler_ctx** pctx = &ctx_array[1]; *pctx;
pctx++) {
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>(*pctx);

if (ctx->trx) {
trx_free_for_mysql(ctx->trx);
ctx->trx = NULL;
}
}

trx_start_if_not_started_xa(prebuilt->trx);

for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) {
@@ -6186,10 +6175,6 @@ ha_innobase::commit_inplace_alter_table(
covering all partitions. */
share->idx_trans_tbl.index_count = 0;

if (trx == ctx0->trx) {
ctx0->trx = NULL;
}

/* Tell the InnoDB server that there might be work for
utility threads: */

@@ -6212,10 +6197,31 @@ ha_innobase::commit_inplace_alter_table(
}

row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
if (trx != ctx0->trx) {
trx_free_for_mysql(trx);
}
DBUG_RETURN(true);
}

if (trx == ctx0->trx) {
ctx0->trx = NULL;
}

/* Free the ctx->trx of other partitions, if any. We will only
use the ctx0->trx here. Others may have been allocated in
the prepare stage. */

for (inplace_alter_handler_ctx** pctx = &ctx_array[1]; *pctx;
pctx++) {
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>(*pctx);

if (ctx->trx) {
trx_free_for_mysql(ctx->trx);
ctx->trx = NULL;
}
}

/* Release the table locks. */
trx_commit_for_mysql(prebuilt->trx);

@@ -4429,12 +4429,16 @@ rollback_inplace_alter_table(
row_mysql_lock_data_dictionary(ctx->trx);

if (ctx->need_rebuild()) {
dberr_t err;
ulint flags = ctx->new_table->flags;

/* DML threads can access ctx->new_table via the
online rebuild log. Free it first. */
innobase_online_rebuild_log_free(prebuilt->table);
}

if (!ctx->new_table) {
ut_ad(ctx->need_rebuild());
} else if (ctx->need_rebuild()) {
dberr_t err;
ulint flags = ctx->new_table->flags;

/* Since the FTS index specific auxiliary tables has
not yet registered with "table->fts" by fts_add_index(),
@@ -5796,21 +5800,6 @@ ha_innobase::commit_inplace_alter_table(
ut_ad(prebuilt->table == ctx0->old_table);
ha_alter_info->group_commit_ctx = NULL;

/* Free the ctx->trx of other partitions, if any. We will only
use the ctx0->trx here. Others may have been allocated in
the prepare stage. */

for (inplace_alter_handler_ctx** pctx = &ctx_array[1]; *pctx;
pctx++) {
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>(*pctx);

if (ctx->trx) {
trx_free_for_mysql(ctx->trx);
ctx->trx = NULL;
}
}

trx_start_if_not_started_xa(prebuilt->trx);

for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) {
@@ -6189,10 +6178,6 @@ ha_innobase::commit_inplace_alter_table(
covering all partitions. */
share->idx_trans_tbl.index_count = 0;

if (trx == ctx0->trx) {
ctx0->trx = NULL;
}

/* Tell the InnoDB server that there might be work for
utility threads: */

@@ -6215,10 +6200,31 @@ ha_innobase::commit_inplace_alter_table(
}

row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
if (trx != ctx0->trx) {
trx_free_for_mysql(trx);
}
DBUG_RETURN(true);
}

if (trx == ctx0->trx) {
ctx0->trx = NULL;
}

/* Free the ctx->trx of other partitions, if any. We will only
use the ctx0->trx here. Others may have been allocated in
the prepare stage. */

for (inplace_alter_handler_ctx** pctx = &ctx_array[1]; *pctx;
pctx++) {
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>(*pctx);

if (ctx->trx) {
trx_free_for_mysql(ctx->trx);
ctx->trx = NULL;
}
}

/* Release the table locks. */
trx_commit_for_mysql(prebuilt->trx);

0 comments on commit 0db66ab

Please sign in to comment.