summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result81
-rw-r--r--mysql-test/r/multi_update.result4
-rw-r--r--mysql-test/r/rpl_transaction.result95
-rw-r--r--mysql-test/r/sp_trans_log.result1
-rw-r--r--mysql-test/r/variables-big.result14
-rw-r--r--mysql-test/t/rpl_transaction-master.opt1
-rw-r--r--mysql-test/t/rpl_transaction-slave.opt1
-rw-r--r--mysql-test/t/rpl_transaction.test106
-rw-r--r--sql/log.cc100
-rw-r--r--sql/log_event.cc1
10 files changed, 331 insertions, 73 deletions
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
index fb69de508dc..bd0c558ea45 100644
--- a/mysql-test/r/mix_innodb_myisam_binlog.result
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -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`; BEGIN
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 select bug27417(2);
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) /* top level non-ta table */;
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 + 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 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 --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index d95036090a5..8a0eacd9eeb 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -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=t1.a;
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 --git a/mysql-test/r/rpl_transaction.result b/mysql-test/r/rpl_transaction.result
new file mode 100644
index 00000000000..9ea0c8f7afd
--- /dev/null
+++ b/mysql-test/r/rpl_transaction.result
@@ -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 #
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+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 #
+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 --git a/mysql-test/r/sp_trans_log.result b/mysql-test/r/sp_trans_log.result
index 9b644798079..eb0770cb0a1 100644
--- a/mysql-test/r/sp_trans_log.result
+++ b/mysql-test/r/sp_trans_log.result
@@ -16,6 +16,7 @@ show binlog events from 98 /* with fixes for #23333 will show there are 2 querie
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 --git a/mysql-test/r/variables-big.result b/mysql-test/r/variables-big.result
index d7906869276..c441f27d82d 100644
--- a/mysql-test/r/variables-big.result
+++ b/mysql-test/r/variables-big.result
@@ -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 --git a/mysql-test/t/rpl_transaction-master.opt b/mysql-test/t/rpl_transaction-master.opt
new file mode 100644
index 00000000000..5411960b4aa
--- /dev/null
+++ b/mysql-test/t/rpl_transaction-master.opt
@@ -0,0 +1 @@
+--innodb --debug=d,do_not_write_xid
diff --git a/mysql-test/t/rpl_transaction-slave.opt b/mysql-test/t/rpl_transaction-slave.opt
new file mode 100644
index 00000000000..627becdbfb5
--- /dev/null
+++ b/mysql-test/t/rpl_transaction-slave.opt
@@ -0,0 +1 @@
+--innodb
diff --git a/mysql-test/t/rpl_transaction.test b/mysql-test/t/rpl_transaction.test
new file mode 100644
index 00000000000..b7912ee274f
--- /dev/null
+++ b/mysql-test/t/rpl_transaction.test
@@ -0,0 +1,106 @@
+# 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/wait_for_slave_to_stop.inc;
+--replace_column 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 #
+query_vertical SHOW SLAVE STATUS;
+# 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 --git a/sql/log.cc b/sql/log.cc
index af03cecd462..eca3cf32228 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -122,6 +122,20 @@ static int binlog_prepare(THD *thd, bool all)
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 all)
// 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 all)
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 *cache, Log_event *commit_event)
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 --git a/sql/log_event.cc b/sql/log_event.cc
index 965dfb5f5cf..a950094a018 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -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));
}