From 8c24f5d14a6f44697630bf641fdb6c48d4357562 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Mon, 30 Nov 2009 12:30:28 +0100 Subject: [PATCH] Bug #20837 Apparent change of isolation level during transaction SET TRANSACTION ISOLATION LEVEL is used to temporarily set the trans.iso.level for the next transaction. After the transaction, the iso.level is (re-)set to value of the session variable 'tx_isolation'. The bug is caused by setting the thd->variables.tx_isolation field to the value of the session variable upon each statement commit. It should only be set at the end of the full transaction. The fix has been to remove the setting of the variable in ha_autocommit_or_rollback if we're in a transaction, as it will be correctly set in either ha_rollback or ha_commit_one_phase. If, on the other hand, we're in autocommit mode, tx_isolation will be explicitly set here. --- mysql-test/r/innodb_mysql.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 26 ++++++++++++++++++++++++++ sql/handler.cc | 10 ++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 402ab3c1b16..2d93cbb47b3 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2273,4 +2273,35 @@ END| DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; +# +# Bug #20837 Apparent change of isolation +# level during transaction +# +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; +SET @@autocommit = 0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT * FROM t1; +s1 +1 +2 +Should be READ UNCOMMITTED +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +INSERT INTO t1 VALUES (-1); +Should be READ UNCOMMITTED +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +COMMIT; +Should now be REPEATABLE READ +SELECT @@tx_isolation; +@@tx_isolation +REPEATABLE-READ +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index a2a1113598d..0462536371e 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -536,4 +536,30 @@ DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; + +--echo # +--echo # Bug #20837 Apparent change of isolation +--echo # level during transaction +--echo # + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; + +SET @@autocommit = 0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT * FROM t1; +--echo Should be READ UNCOMMITTED +SELECT @@tx_isolation; +INSERT INTO t1 VALUES (-1); +--echo Should be READ UNCOMMITTED +SELECT @@tx_isolation; +COMMIT; +--echo Should now be REPEATABLE READ +SELECT @@tx_isolation; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/handler.cc b/sql/handler.cc index 216228ed509..f6cdaca05bd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1369,8 +1369,14 @@ int ha_autocommit_or_rollback(THD *thd, int error) if (thd->transaction_rollback_request && !thd->in_sub_stmt) (void) ha_rollback(thd); } - - thd->variables.tx_isolation=thd->session_tx_isolation; + } + else if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + { + /* + If we're in autocommit mode, reset tx_isolation + to the default value + */ + thd->variables.tx_isolation= thd->session_tx_isolation; } #endif DBUG_RETURN(error);