From 17b9155f00f9f80c1c1f15bb98baebe21ac2a9e1 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 20 Jul 2010 14:36:15 -0300 Subject: [PATCH] Bug#54453: Failing assertion: trx->active_trans when renaming a table with active trx Essentially, the problem is that InnoDB does a implicit commit when a cursor (table handler) is unlocked/closed, creating a dissonance between the transaction state within the server layer and the storage engine layer. Theoretically, a statement transaction can encompass several table instances in a similar manner to a multiple statement transaction, hence it does not make sense to limit a statement transaction to the lifetime of the table instances (cursors) used within it. Since this particular instance of the problem is only triggerable on 5.1 and is masked on 5.5 due 2PC being skipped (assertion is in the prepare phase of a 2PC), the solution (which is less risky) is to explicitly end the transaction before the cached table is unlock on rename table. The patch is to be null merged into trunk. --- mysql-test/include/commit.inc | 4 ++-- mysql-test/r/commit_1innodb.result | 4 ++-- .../suite/innodb_plugin/r/innodb_bug54453.result | 9 +++++++++ .../suite/innodb_plugin/t/innodb_bug54453.test | 15 +++++++++++++++ sql/sql_table.cc | 8 ++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug54453.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug54453.test diff --git a/mysql-test/include/commit.inc b/mysql-test/include/commit.inc index d91ba8291fd..d412eae8364 100644 --- a/mysql-test/include/commit.inc +++ b/mysql-test/include/commit.inc @@ -725,9 +725,9 @@ call p_verify_status_increment(4, 4, 4, 4); alter table t3 add column (b int); call p_verify_status_increment(2, 0, 2, 0); alter table t3 rename t4; -call p_verify_status_increment(2, 2, 2, 2); +call p_verify_status_increment(1, 0, 1, 0); rename table t4 to t3; -call p_verify_status_increment(2, 2, 2, 2); +call p_verify_status_increment(1, 0, 1, 0); truncate table t3; call p_verify_status_increment(4, 4, 4, 4); create view v1 as select * from t2; diff --git a/mysql-test/r/commit_1innodb.result b/mysql-test/r/commit_1innodb.result index 51c4ac3002c..1f0b2c8019b 100644 --- a/mysql-test/r/commit_1innodb.result +++ b/mysql-test/r/commit_1innodb.result @@ -841,11 +841,11 @@ call p_verify_status_increment(2, 0, 2, 0); SUCCESS alter table t3 rename t4; -call p_verify_status_increment(2, 2, 2, 2); +call p_verify_status_increment(1, 0, 1, 0); SUCCESS rename table t4 to t3; -call p_verify_status_increment(2, 2, 2, 2); +call p_verify_status_increment(1, 0, 1, 0); SUCCESS truncate table t3; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54453.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54453.result new file mode 100644 index 00000000000..e623989a9d4 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug54453.result @@ -0,0 +1,9 @@ +# +# Bug#54453: Failing assertion: trx->active_trans when renaming a table with active trx +# +DROP TABLE IF EXISTS bug54453; +CREATE TABLE bug54453(a INT) ENGINE=InnoDB; +ALTER TABLE bug54453 RENAME TO bug54453_2; +SELECT * FROM bug54453_2; +a +DROP TABLE bug54453_2; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54453.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54453.test new file mode 100644 index 00000000000..486695d326d --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug54453.test @@ -0,0 +1,15 @@ +--source include/have_innodb_plugin.inc +--source include/have_log_bin.inc + +--echo # +--echo # Bug#54453: Failing assertion: trx->active_trans when renaming a table with active trx +--echo # + +--disable_warnings +DROP TABLE IF EXISTS bug54453; +--enable_warnings + +CREATE TABLE bug54453(a INT) ENGINE=InnoDB; +ALTER TABLE bug54453 RENAME TO bug54453_2; +SELECT * FROM bug54453_2; +DROP TABLE bug54453_2; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 50045ec6d90..47b91fcca0e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6848,6 +6848,14 @@ view_err: if (!error && (new_name != table_name || new_db != db)) { thd_proc_info(thd, "rename"); + + /* + Workaround InnoDB ending the transaction when the table instance + is unlocked/closed (close_cached_table below), otherwise the trx + state will differ between the server and storage engine layers. + */ + ha_autocommit_or_rollback(thd, 0); + /* Then do a 'simple' rename of the table. First we need to close all instances of 'source' table.