summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMats Kindahl <mats@sun.com>2009-09-23 13:20:48 +0200
committerMats Kindahl <mats@sun.com>2009-09-23 13:20:48 +0200
commit8f35f7c907992c77b1bda584956cf8acf97e88d5 (patch)
tree05f9e5a91777fffa20de0e533bfef022ed954374
parent5661e72623e66d9170dbe3e7913ff4f36b79100d (diff)
downloadmariadb-git-8f35f7c907992c77b1bda584956cf8acf97e88d5.tar.gz
Bug #37221: SET AUTOCOMMIT=1 does not commit binary log
When setting AUTOCOMMIT=1 after starting a transaction, the binary log did not commit the outstanding transaction. The reason was that the binary log commit function saw the values of the new settings, deciding that there were nothing to commit. Fixed the problem by moving the implicit commit to before the thread option flags were changed, so that the binary log sees the old values of the flags instead of the values they will take after the statement.
-rw-r--r--mysql-test/extra/binlog_tests/implicit.test28
-rw-r--r--mysql-test/suite/binlog/r/binlog_implicit_commit.result345
-rw-r--r--mysql-test/suite/binlog/t/binlog_implicit_commit.test63
-rw-r--r--sql/set_var.cc11
4 files changed, 445 insertions, 2 deletions
diff --git a/mysql-test/extra/binlog_tests/implicit.test b/mysql-test/extra/binlog_tests/implicit.test
new file mode 100644
index 00000000000..84d80288d36
--- /dev/null
+++ b/mysql-test/extra/binlog_tests/implicit.test
@@ -0,0 +1,28 @@
+# First part: outside a transaction
+RESET MASTER;
+eval $prepare;
+
+INSERT INTO t1 VALUES (1);
+source include/show_binlog_events.inc;
+eval $statement;
+source include/show_binlog_events.inc;
+if (`select '$cleanup' != ''`) {
+ eval $cleanup;
+}
+
+# Second part: inside a transaction
+RESET MASTER;
+eval $prepare;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+source include/show_binlog_events.inc;
+eval $statement;
+source include/show_binlog_events.inc;
+INSERT INTO t1 VALUES (3);
+source include/show_binlog_events.inc;
+COMMIT;
+source include/show_binlog_events.inc;
+if (`select '$cleanup' != ''`) {
+ eval $cleanup;
+}
+
diff --git a/mysql-test/suite/binlog/r/binlog_implicit_commit.result b/mysql-test/suite/binlog/r/binlog_implicit_commit.result
new file mode 100644
index 00000000000..ea43b31bde9
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_implicit_commit.result
@@ -0,0 +1,345 @@
+CREATE TABLE t1 (id INT) ENGINE = InnoDB;
+SET BINLOG_FORMAT = STATEMENT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Xid # # COMMIT /* XID */
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (2)
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (3)
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+SET BINLOG_FORMAT = ROW;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 1;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET AUTOCOMMIT = 0;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+INSERT INTO t1 VALUES (3);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+LOCK TABLES t1 WRITE;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+INSERT INTO t1 VALUES (2);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+UNLOCK TABLES;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_implicit_commit.test b/mysql-test/suite/binlog/t/binlog_implicit_commit.test
new file mode 100644
index 00000000000..a682ab95e3d
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_implicit_commit.test
@@ -0,0 +1,63 @@
+# The purpose of this test is to test that setting autocommit does a
+# commit of outstanding transactions and nothing is left pending in
+# the transaction cache.
+
+source include/have_log_bin.inc;
+source include/have_innodb.inc;
+
+# We need a transactional engine, so let's use InnoDB
+CREATE TABLE t1 (id INT) ENGINE = InnoDB;
+
+# Testing SET AUTOCOMMIT
+SET BINLOG_FORMAT = STATEMENT;
+
+let $cleanup = COMMIT;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 1;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 1;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 0;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 0;
+source extra/binlog_tests/implicit.test;
+
+SET BINLOG_FORMAT = ROW;
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 1;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 1;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 0;
+let $statement = SET AUTOCOMMIT = 0;
+source extra/binlog_tests/implicit.test;
+
+let $prepare = SET AUTOCOMMIT = 1;
+let $statement = SET AUTOCOMMIT = 0;
+source extra/binlog_tests/implicit.test;
+
+RESET MASTER;
+SET AUTOCOMMIT = 0;
+INSERT INTO t1 VALUES (1);
+source include/show_binlog_events.inc;
+LOCK TABLES t1 WRITE;
+source include/show_binlog_events.inc;
+INSERT INTO t1 VALUES (2);
+source include/show_binlog_events.inc;
+UNLOCK TABLES;
+source include/show_binlog_events.inc;
+COMMIT;
+source include/show_binlog_events.inc;
+
+# Cleaning up
+DROP TABLE t1;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 0b89333ce03..5025356230c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3054,6 +3054,15 @@ static bool set_option_autocommit(THD *thd, set_var *var)
ulonglong org_options= thd->options;
+ /*
+ If we are setting AUTOCOMMIT=1 and it was not already 1, then we
+ need to commit any outstanding transactions.
+ */
+ if (var->save_result.ulong_value != 0 &&
+ (thd->options & OPTION_NOT_AUTOCOMMIT) &&
+ ha_commit(thd))
+ return 1;
+
if (var->save_result.ulong_value != 0)
thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
else
@@ -3067,8 +3076,6 @@ static bool set_option_autocommit(THD *thd, set_var *var)
thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
- if (ha_commit(thd))
- return 1;
}
else
{