List:Commits« Previous MessageNext Message »
From:Sven Sandberg Date:December 18 2007 4:08pm
Subject:bk commit into 5.0 tree (sven:1.2558) BUG#26395
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of sven. When sven does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-12-18 17:08:28+01:00, sven@riska.(none) +11 -0
  BUG#26395: if crash during autocommit update to transactional table on master, slave fails
  Now, every transaction (including autocommit transactions) start with
  a BEGIN and end with a COMMIT/ROLLBACK in the binlog.
  Added a test case, and updated lots of test case result files.

  mysql-test/include/show_slave_status.inc@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +6 -0
    Copied show_slave_status.inc from 5.1

  mysql-test/include/show_slave_status.inc@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +0 -0

  mysql-test/r/mix_innodb_myisam_binlog.result@stripped, 2007-12-18 17:08:25+01:00, sven@riska.(none) +44 -37
    updated result file

  mysql-test/r/multi_update.result@stripped, 2007-12-18 17:08:25+01:00, sven@riska.(none) +2 -2
    updated result file

  mysql-test/r/rpl_transaction.result@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +95 -0
    New result file for new test case.

  mysql-test/r/rpl_transaction.result@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +0 -0

  mysql-test/r/sp_trans_log.result@stripped, 2007-12-18 17:08:25+01:00, sven@riska.(none) +1 -0
    updated result file

  mysql-test/r/variables-big.result@stripped, 2007-12-18 17:08:25+01:00, sven@riska.(none) +9 -5
    updated result file

  mysql-test/t/rpl_transaction-master.opt@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +1 -0
    Options for new test case.

  mysql-test/t/rpl_transaction-master.opt@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +0 -0

  mysql-test/t/rpl_transaction-slave.opt@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +1 -0
    Options for new test case

  mysql-test/t/rpl_transaction-slave.opt@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +0 -0

  mysql-test/t/rpl_transaction.test@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +104 -0
    Added new test case.

  mysql-test/t/rpl_transaction.test@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +0 -0

  sql/log.cc@stripped, 2007-12-18 17:08:25+01:00, sven@riska.(none) +71 -29
     - Always write BEGIN and COMMIT around statements, even in autocommit
       mode.
     - Added comments for binlog_commit and binlog_rollback.

  sql/log_event.cc@stripped, 2007-12-18 17:08:26+01:00, sven@riska.(none) +1 -0
    Added debug trigger to avoid writing xid events to the binlog.

diff -Nrup a/mysql-test/include/show_slave_status.inc b/mysql-test/include/show_slave_status.inc
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/include/show_slave_status.inc	2007-12-18 17:08:26 +01:00
@@ -0,0 +1,6 @@
+# Include file to show the slave status, masking out some information
+# that varies depending on where the test is executed.
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 1 # 8 # 9 # 16 # 23 # 33 # 35 # 36 #
+query_vertical SHOW SLAVE STATUS;
diff -Nrup a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
--- a/mysql-test/r/mix_innodb_myisam_binlog.result	2007-10-13 14:49:37 +02:00
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result	2007-12-18 17:08:25 +01:00
@@ -100,9 +100,10 @@ insert into t1 values(9);
 insert into t2 select * from t1;
 show binlog events from 98;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(9)
-master-bin.000001	185	Xid	1	#	COMMIT /* XID */
-master-bin.000001	212	Query	1	#	use `test`; insert into t2 select * from t1
+master-bin.000001	98	Query	1	#	use `test`; BEGIN
+master-bin.000001	166	Query	1	#	use `test`; insert into t1 values(9)
+master-bin.000001	253	Xid	1	#	COMMIT /* XID */
+master-bin.000001	280	Query	1	#	use `test`; insert into t2 select * from t1
 delete from t1;
 delete from t2;
 reset master;
@@ -111,19 +112,21 @@ begin;
 insert into t2 select * from t1;
 show binlog events from 98;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(10)
-master-bin.000001	186	Xid	1	#	COMMIT /* XID */
-master-bin.000001	213	Query	1	#	use `test`; insert into t2 select * from t1
+master-bin.000001	98	Query	1	#	use `test`; BEGIN
+master-bin.000001	166	Query	1	#	use `test`; insert into t1 values(10)
+master-bin.000001	254	Xid	1	#	COMMIT /* XID */
+master-bin.000001	281	Query	1	#	use `test`; insert into t2 select * from t1
 insert into t1 values(11);
 commit;
 show binlog events from 98;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(10)
-master-bin.000001	186	Xid	1	#	COMMIT /* XID */
-master-bin.000001	213	Query	1	#	use `test`; insert into t2 select * from t1
-master-bin.000001	307	Query	1	#	use `test`; BEGIN
-master-bin.000001	375	Query	1	#	use `test`; insert into t1 values(11)
-master-bin.000001	463	Xid	1	#	COMMIT /* XID */
+master-bin.000001	98	Query	1	#	use `test`; BEGIN
+master-bin.000001	166	Query	1	#	use `test`; insert into t1 values(10)
+master-bin.000001	254	Xid	1	#	COMMIT /* XID */
+master-bin.000001	281	Query	1	#	use `test`; insert into t2 select * from t1
+master-bin.000001	375	Query	1	#	use `test`; BEGIN
+master-bin.000001	443	Query	1	#	use `test`; insert into t1 values(11)
+master-bin.000001	531	Xid	1	#	COMMIT /* XID */
 alter table t2 engine=INNODB;
 delete from t1;
 delete from t2;
@@ -235,25 +238,29 @@ master-bin.000001	98	Query	1	#	use `test
 master-bin.000001	166	Query	1	#	use `test`; insert into t1 values(16)
 master-bin.000001	254	Query	1	#	use `test`; insert into t1 values(18)
 master-bin.000001	342	Xid	1	#	COMMIT /* XID */
-master-bin.000001	369	Query	1	#	use `test`; delete from t1
-master-bin.000001	446	Xid	1	#	COMMIT /* XID */
-master-bin.000001	473	Query	1	#	use `test`; delete from t2
-master-bin.000001	550	Xid	1	#	COMMIT /* XID */
-master-bin.000001	577	Query	1	#	use `test`; alter table t2 type=MyISAM
-master-bin.000001	666	Query	1	#	use `test`; insert into t1 values (1)
-master-bin.000001	754	Xid	1	#	COMMIT /* XID */
-master-bin.000001	781	Query	1	#	use `test`; insert into t2 values (20)
-master-bin.000001	870	Query	1	#	use `test`; drop table t1,t2
-master-bin.000001	949	Query	1	#	use `test`; create temporary table ti (a int) engine=innodb
-master-bin.000001	1059	Query	1	#	use `test`; insert into ti values(1)
-master-bin.000001	1146	Xid	1	#	COMMIT /* XID */
-master-bin.000001	1173	Query	1	#	use `test`; create temporary table t1 (a int) engine=myisam
-master-bin.000001	1283	Query	1	#	use `test`; insert t1 values (1)
-master-bin.000001	1366	Query	1	#	use `test`; create table t0 (n int)
-master-bin.000001	1452	Query	1	#	use `test`; insert t0 select * from t1
-master-bin.000001	1541	Query	1	#	use `test`; insert into t0 select GET_LOCK("lock1",null)
-master-bin.000001	1648	Query	1	#	use `test`; create table t2 (n int) engine=innodb
-master-bin.000001	1748	Query	1	#	use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
+master-bin.000001	369	Query	1	#	use `test`; BEGIN
+master-bin.000001	437	Query	1	#	use `test`; delete from t1
+master-bin.000001	514	Xid	1	#	COMMIT /* XID */
+master-bin.000001	541	Query	1	#	use `test`; BEGIN
+master-bin.000001	609	Query	1	#	use `test`; delete from t2
+master-bin.000001	686	Xid	1	#	COMMIT /* XID */
+master-bin.000001	713	Query	1	#	use `test`; alter table t2 type=MyISAM
+master-bin.000001	802	Query	1	#	use `test`; BEGIN
+master-bin.000001	870	Query	1	#	use `test`; insert into t1 values (1)
+master-bin.000001	958	Xid	1	#	COMMIT /* XID */
+master-bin.000001	985	Query	1	#	use `test`; insert into t2 values (20)
+master-bin.000001	1074	Query	1	#	use `test`; drop table t1,t2
+master-bin.000001	1153	Query	1	#	use `test`; create temporary table ti (a int) engine=innodb
+master-bin.000001	1263	Query	1	#	use `test`; BEGIN
+master-bin.000001	1331	Query	1	#	use `test`; insert into ti values(1)
+master-bin.000001	1418	Xid	1	#	COMMIT /* XID */
+master-bin.000001	1445	Query	1	#	use `test`; create temporary table t1 (a int) engine=myisam
+master-bin.000001	1555	Query	1	#	use `test`; insert t1 values (1)
+master-bin.000001	1638	Query	1	#	use `test`; create table t0 (n int)
+master-bin.000001	1724	Query	1	#	use `test`; insert t0 select * from t1
+master-bin.000001	1813	Query	1	#	use `test`; insert into t0 select GET_LOCK("lock1",null)
+master-bin.000001	1920	Query	1	#	use `test`; create table t2 (n int) engine=innodb
+master-bin.000001	2020	Query	1	#	use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
 do release_lock("lock1");
 drop table t0,t2;
 reset master;
@@ -402,7 +409,7 @@ insert into t2 values (bug27417(1));
 ERROR 23000: Duplicate entry '1' for key 1
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	267		
+master-bin.000001	335		
 select count(*) from t1 /* must be 1 */;
 count(*)
 1
@@ -414,7 +421,7 @@ insert into t2 select bug27417(1) union 
 ERROR 23000: Duplicate entry '2' for key 1
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	290		
+master-bin.000001	358		
 select count(*) from t1 /* must be 2 */;
 count(*)
 2
@@ -438,7 +445,7 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1)
 ERROR 23000: Duplicate entry '2' for key 1
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	301		
+master-bin.000001	369		
 select count(*) from t1 /* must be 4 */;
 count(*)
 4
@@ -466,7 +473,7 @@ delete from t2;
 ERROR 23000: Duplicate entry '1' for key 1
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	246		
+master-bin.000001	314		
 select count(*) from t1 /* must be 1 */;
 count(*)
 1
@@ -483,7 +490,7 @@ delete t2.* from t2,t5 where t2.a=t5.a +
 ERROR 23000: Duplicate entry '1' for key 1
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	274		
+master-bin.000001	342		
 select count(*) from t1 /* must be 1 */;
 count(*)
 1
@@ -501,7 +508,7 @@ count(*)
 2
 show master status /* the offset must denote there is the query */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	376		
+master-bin.000001	444		
 drop trigger trg_del_t2;
 drop table t1,t2,t3,t4,t5;
 drop function bug27417;
diff -Nrup a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
--- a/mysql-test/r/multi_update.result	2007-10-13 14:49:37 +02:00
+++ b/mysql-test/r/multi_update.result	2007-12-18 17:08:25 +01:00
@@ -545,7 +545,7 @@ a	b
 4	4
 show master status /* there must be the UPDATE query event */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	260		
+master-bin.000001	328		
 delete from t1;
 delete from t2;
 insert into t1 values (1,2),(3,4),(4,4);
@@ -555,7 +555,7 @@ UPDATE t2,t1  SET t2.a=t2.b where t2.a=t
 ERROR 23000: Duplicate entry '4' for key 1
 show master status /* there must be the UPDATE query event */;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
-master-bin.000001	275		
+master-bin.000001	343		
 drop table t1, t2;
 drop table if exists t1, t2, t3;
 CREATE TABLE t1 (a int, PRIMARY KEY (a));
diff -Nrup a/mysql-test/r/rpl_transaction.result b/mysql-test/r/rpl_transaction.result
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/r/rpl_transaction.result	2007-12-18 17:08:26 +01:00
@@ -0,0 +1,95 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE tmyisam (a int) ENGINE = MYISAM;
+CREATE TABLE tinnodb (a int) ENGINE = INNODB;
+SHOW CREATE TABLE tmyisam;
+Table	Create Table
+tmyisam	CREATE TABLE `tmyisam` (
+  `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW CREATE TABLE tinnodb;
+Table	Create Table
+tinnodb	CREATE TABLE `tinnodb` (
+  `a` int(11) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+==== Test 1: Non-XA Engines ====
+--- on master ---
+SET AUTOCOMMIT = 1;
+INSERT INTO tmyisam VALUES (1);
+BEGIN;
+INSERT INTO tmyisam VALUES (2);
+INSERT INTO tmyisam VALUES (3);
+COMMIT;
+BEGIN;
+INSERT INTO tmyisam VALUES (5);
+INSERT INTO tmyisam VALUES (6);
+ROLLBACK;
+Warnings:
+Warning	1196	Some non-transactional changed tables couldn't be rolled back
+SELECT * FROM tmyisam ORDER BY a;
+a
+1
+2
+3
+5
+6
+--- on slave ---
+SELECT * FROM tmyisam ORDER BY a;
+a
+1
+2
+3
+5
+6
+==== Test 2: Master crash before writing XID event on XA engine ====
+--- on master ---
+INSERT INTO tinnodb VALUES (1);
+SELECT * FROM tinnodb ORDER BY a;
+a
+1
+--- on slave ---
+STOP SLAVE;
+SHOW SLAVE STATUS;
+Slave_IO_State	#
+Master_Host	127.0.0.1
+Master_User	root
+Master_Port	MASTER_PORT
+Connect_Retry	1
+Master_Log_File	master-bin.000001
+Read_Master_Log_Pos	938
+Relay_Log_File	#
+Relay_Log_Pos	#
+Relay_Master_Log_File	master-bin.000001
+Slave_IO_Running	No
+Slave_SQL_Running	No
+Replicate_Do_DB	
+Replicate_Ignore_DB	
+Replicate_Do_Table	
+Replicate_Ignore_Table	#
+Replicate_Wild_Do_Table	
+Replicate_Wild_Ignore_Table	
+Last_Errno	0
+Last_Error	
+Skip_Counter	0
+Exec_Master_Log_Pos	777
+Relay_Log_Space	#
+Until_Condition	None
+Until_Log_File	
+Until_Log_Pos	0
+Master_SSL_Allowed	No
+Master_SSL_CA_File	
+Master_SSL_CA_Path	
+Master_SSL_Cert	
+Master_SSL_Cipher	
+Master_SSL_Key	
+Seconds_Behind_Master	#
+SELECT * FROM tinnodb ORDER BY a;
+a
+DROP TABLE tmyisam;
+DROP TABLE tinnodb;
+DROP TABLE tmyisam;
+DROP TABLE tinnodb;
diff -Nrup a/mysql-test/r/sp_trans_log.result b/mysql-test/r/sp_trans_log.result
--- a/mysql-test/r/sp_trans_log.result	2007-08-22 14:43:13 +02:00
+++ b/mysql-test/r/sp_trans_log.result	2007-12-18 17:08:25 +01:00
@@ -16,6 +16,7 @@ show binlog events from 98 /* with fixes
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 master-bin.000001	#	Query	1	#	#
 master-bin.000001	#	Query	1	#	#
+master-bin.000001	#	Query	1	#	#
 select count(*),@a from t1 /* must be 1,1 */|
 count(*)	@a
 1	1
diff -Nrup a/mysql-test/r/variables-big.result b/mysql-test/r/variables-big.result
--- a/mysql-test/r/variables-big.result	2007-04-13 00:03:24 +02:00
+++ b/mysql-test/r/variables-big.result	2007-12-18 17:08:25 +01:00
@@ -1,20 +1,24 @@
 set session transaction_prealloc_size=1024*1024*1024*1;
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
-1	root	localhost	test	Query	0	NULL	show processlist
+6	root	localhost	test	Query	0	NULL	show processlist
 set session transaction_prealloc_size=1024*1024*1024*2;
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
-1	root	localhost	test	Query	2	NULL	show processlist
+6	root	localhost	test	Query	1	NULL	show processlist
 set session transaction_prealloc_size=1024*1024*1024*3;
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
-1	root	localhost	test	Query	0	NULL	show processlist
+6	root	localhost	test	Query	0	NULL	show processlist
 set session transaction_prealloc_size=1024*1024*1024*4;
+Warnings:
+Warning	1292	Truncated incorrect transaction_prealloc_size value: '4294967296'
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
-1	root	localhost	test	Query	0	NULL	show processlist
+6	root	localhost	test	Query	0	NULL	show processlist
 set session transaction_prealloc_size=1024*1024*1024*5;
+Warnings:
+Warning	1292	Truncated incorrect transaction_prealloc_size value: '5368709120'
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
-1	root	localhost	test	Query	0	NULL	show processlist
+6	root	localhost	test	Query	0	NULL	show processlist
diff -Nrup a/mysql-test/t/rpl_transaction-master.opt b/mysql-test/t/rpl_transaction-master.opt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_transaction-master.opt	2007-12-18 17:08:26 +01:00
@@ -0,0 +1 @@
+--innodb --debug=d,do_not_write_xid
diff -Nrup a/mysql-test/t/rpl_transaction-slave.opt b/mysql-test/t/rpl_transaction-slave.opt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_transaction-slave.opt	2007-12-18 17:08:26 +01:00
@@ -0,0 +1 @@
+--innodb
diff -Nrup a/mysql-test/t/rpl_transaction.test b/mysql-test/t/rpl_transaction.test
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/rpl_transaction.test	2007-12-18 17:08:26 +01:00
@@ -0,0 +1,104 @@
+# Tests that transactions are replicated correctly, with various
+# combinations of non-transactional and transactional non-XA tables.
+# Also tests that an XA transaction where the master crashes just
+# before writing the XID log event is executed correctly.  See below
+# for implementation details.
+
+# Note: this test should not exist in 5.1 or higher.  It has been
+# replaced by rpl_ndb_transaction.test, which tests a superset of what
+# this test tests.
+
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+
+CREATE TABLE tmyisam (a int) ENGINE = MYISAM;
+CREATE TABLE tinnodb (a int) ENGINE = INNODB;
+
+SHOW CREATE TABLE tmyisam;
+SHOW CREATE TABLE tinnodb;
+
+
+--echo ==== Test 1: Non-XA Engines ====
+# Test that everything works fine with non-XA engines.  We just try
+# all ways to do transactions involving ndb and/or myisam, with
+# rollback or commit.
+
+--echo --- on master ---
+
+SET AUTOCOMMIT = 1;
+
+INSERT INTO tmyisam VALUES (1);
+
+BEGIN;
+INSERT INTO tmyisam VALUES (2);
+INSERT INTO tmyisam VALUES (3);
+COMMIT;
+
+BEGIN;
+INSERT INTO tmyisam VALUES (5);
+INSERT INTO tmyisam VALUES (6);
+--warning 1196
+ROLLBACK;
+
+SELECT * FROM tmyisam ORDER BY a;
+
+--echo --- on slave ---
+--sync_slave_with_master
+SELECT * FROM tmyisam ORDER BY a;
+
+
+--echo ==== Test 2: Master crash before writing XID event on XA engine ====
+# We now want to test the following scenario, to verify that BUG#26395
+# has been fixed:
+
+#   "master and slave have a transactional table that uses XA. Master
+#    has AUTOCOMMIT on and executes a statement (in this case an
+#    INSERT). Master crashes just before writing the XID event."
+
+# In this scenario, master will roll back, so slave should not execute
+# the statement, and slave should roll back later when master is
+# restarted.
+
+# However, we the master to be alive so that we are sure it replicates
+# the statement to the slave. So in the test case, we must therefore
+# not crash the master. Instead, we fake the crash by just not writing
+# the XID event to the binlog. This is done by the
+# --debug=d,do_not_write_xid flag in the .opt file.
+
+# So, unlike if the master had crashed, the master *will* execute the
+# statement. But the slave should not execute it. Hence, after the
+# first test is executed, the expected result on master is a table
+# with one row, and on slave a table with no rows.
+
+# To simulate the slave correctly, we wait until everything up to the
+# XID is replicated. We cannot sync_slave_with_master, because that
+# would wait for the transaction to end. Instead, we wait for
+# "sufficiently long time". Then we stop the slave.
+
+# Note: since this puts the master binlog in an inconsistent state,
+# this should be the last test of the file.
+
+--echo --- on master ---
+--connection master
+
+INSERT INTO tinnodb VALUES (1);
+SELECT * FROM tinnodb ORDER BY a;
+
+--echo --- on slave ---
+--connection slave
+--sleep 3
+STOP SLAVE;
+--source include/show_slave_status.inc
+# the following statement should show that nothing has been replicated
+SELECT * FROM tinnodb ORDER BY a;
+
+
+# clean up
+connection master;
+DROP TABLE tmyisam;
+DROP TABLE tinnodb;
+
+connection slave;
+DROP TABLE tmyisam;
+DROP TABLE tinnodb;
diff -Nrup a/sql/log.cc b/sql/log.cc
--- a/sql/log.cc	2007-11-05 16:20:08 +01:00
+++ b/sql/log.cc	2007-12-18 17:08:25 +01:00
@@ -122,6 +122,20 @@ static int binlog_prepare(THD *thd, bool
   return 0;
 }
 
+/**
+  This function is called once after each statement.
+
+  It has the responsibility to flush the transaction cache to the
+  binlog file on commits.
+
+  @param thd   The client thread that executes the transaction.
+  @param all   true if this is the last statement before a COMMIT
+               statement; false if either this is a statement in a
+               transaction but not the last, or if this is a statement
+               not inside a BEGIN block and autocommit is on.
+
+  @see handlerton::commit
+*/
 static int binlog_commit(THD *thd, bool all)
 {
   IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
@@ -134,7 +148,15 @@ static int binlog_commit(THD *thd, bool 
     // we're here because trans_log was flushed in MYSQL_LOG::log_xid()
     DBUG_RETURN(0);
   }
-  if (all)
+  /*
+    Write commit event if at least one of the following holds:
+     - the user sends an explicit COMMIT; or
+     - the autocommit flag is on, and we are not inside a BEGIN.
+    However, if the user has not sent an explicit COMMIT, and we are
+    either inside a BEGIN or run with autocommit off, then this is not
+    the end of a transaction and we should not write a commit event.
+  */
+  if (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
   {
     Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
     qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
@@ -144,6 +166,22 @@ static int binlog_commit(THD *thd, bool 
     DBUG_RETURN(binlog_end_trans(thd, trans_log, &invisible_commit));
 }
 
+/**
+  This function is called when a transaction involving a transactional
+  table is rolled back.
+
+  It has the responsibility to flush the transaction cache to the
+  binlog file. However, if the transaction does not involve
+  non-transactional tables, nothing needs to be logged.
+
+  @param thd   The client thread that executes the transaction.
+  @param all   true if this is the last statement before a COMMIT
+               statement; false if either this is a statement in a
+               transaction but not the last, or if this is a statement
+               not inside a BEGIN block and autocommit is on.
+
+  @see handlerton::rollback
+*/
 static int binlog_rollback(THD *thd, bool all)
 {
   int error=0;
@@ -1817,9 +1855,11 @@ uint MYSQL_LOG::next_file_id()
   IMPLEMENTATION
     - To support transaction over replication, we wrap the transaction
       with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
-      We want to write a BEGIN/ROLLBACK block when a non-transactional table
-      was updated in a transaction which was rolled back. This is to ensure
-      that the same updates are run on the slave.
+      If a transaction that only involves transactional tables is
+      rolled back, we do not binlog it. However, we write a
+      BEGIN/ROLLBACK block when a non-transactional table was updated
+      in a transaction which was rolled back. This is to ensure that
+      the same updates are run on the slave.
 */
 
 bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
@@ -1837,32 +1877,34 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE
     byte header[LOG_EVENT_HEADER_LEN];
 
     /*
-      Log "BEGIN" at the beginning of the transaction.
-      which may contain more than 1 SQL statement.
+      Log "BEGIN" at the beginning of every transaction.  Here, a
+      transaction is either a BEGIN..COMMIT block or a single
+      statement in autocommit mode.
     */
-    if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
-    {
-      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE);
-      /*
-        Imagine this is rollback due to net timeout, after all statements of
-        the transaction succeeded. Then we want a zero-error code in BEGIN.
-        In other words, if there was a really serious error code it's already
-        in the statement's events, there is no need to put it also in this
-        internally generated event, and as this event is generated late it
-        would lead to false alarms.
-        This is safer than thd->clear_error() against kills at shutdown.
-      */
-      qinfo.error_code= 0;
-      /*
-        Now this Query_log_event has artificial log_pos 0. It must be adjusted
-        to reflect the real position in the log. Not doing it would confuse the
-	slave: it would prevent this one from knowing where he is in the
-	master's binlog, which would result in wrong positions being shown to
-	the user, MASTER_POS_WAIT undue waiting etc.
-      */
-      if (qinfo.write(&log_file))
-	goto err;
-    }
+    Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE);
+    /*
+      Imagine this is rollback due to net timeout, after all
+      statements of the transaction succeeded. Then we want a
+      zero-error code in BEGIN.  In other words, if there was a
+      really serious error code it's already in the statement's
+      events, there is no need to put it also in this internally
+      generated event, and as this event is generated late it would
+      lead to false alarms.
+
+      This is safer than thd->clear_error() against kills at shutdown.
+    */
+    qinfo.error_code= 0;
+    /*
+      Now this Query_log_event has artificial log_pos 0. It must be
+      adjusted to reflect the real position in the log. Not doing it
+      would confuse the slave: it would prevent this one from
+      knowing where he is in the master's binlog, which would result
+      in wrong positions being shown to the user, MASTER_POS_WAIT
+      undue waiting etc.
+    */
+    if (qinfo.write(&log_file))
+      goto err;
+
     /* Read from the file used to cache the queries .*/
     if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
       goto err;
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-11-13 09:43:25 +01:00
+++ b/sql/log_event.cc	2007-12-18 17:08:26 +01:00
@@ -3793,6 +3793,7 @@ Xid_log_event(const char* buf,
 #ifndef MYSQL_CLIENT
 bool Xid_log_event::write(IO_CACHE* file)
 {
+  DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
   return write_header(file, sizeof(xid)) ||
          my_b_safe_write(file, (byte*) &xid, sizeof(xid));
 }
Thread
bk commit into 5.0 tree (sven:1.2558) BUG#26395Sven Sandberg18 Dec