Commit ab396c1d authored by sven@riska.(none)'s avatar sven@riska.(none)

BUG#26395: if crash during autocommit update to transactional table on master, slave fails

Now, every transaction (including autocommit transactions) starts with
a BEGIN and ends with a COMMIT/ROLLBACK in the binlog.
Added a test case, and updated lots of test case result files.
parent 45f6c038
......@@ -627,7 +627,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 268
master-bin.000001 336
delete from t1;
delete from t2;
insert into t1 values (1,2),(3,4),(4,4);
......@@ -637,7 +637,7 @@ UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
show master status /* there must be the UPDATE query event */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 283
master-bin.000001 351
drop table t1, t2;
set @@session.binlog_format= @sav_binlog_format;
drop table if exists t1, t2, t3;
......
......@@ -16,6 +16,7 @@ insert into t2 values (bug23333(),1)|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
show binlog events from 106 /* with fixes for #23333 will show there is the query */|
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # #
master-bin.000001 # Table_map 1 # #
master-bin.000001 # Table_map 1 # #
master-bin.000001 # Write_rows 1 # #
......
......@@ -66,6 +66,7 @@ COMMIT;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=INNODB
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
......
......@@ -18,8 +18,12 @@ TRUNCATE t1n;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f
......@@ -49,8 +53,12 @@ TRUNCATE t1n;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; TRUNCATE t1m
master-bin.000001 # Query # # use `test`; TRUNCATE t1b
master-bin.000001 # Query # # BEGIN
......
......@@ -108,19 +108,35 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; drop table t1,t2
master-bin.000001 # Query # # use `test`; create table t1 (a int) engine=blackhole
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; delete from t1 where a=10
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; update t1 set a=11 where a=15
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values(1)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert ignore into t1 values(1)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; replace into t1 values(100)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; create table t2 (a varchar(200)) engine=blackhole
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Begin_load_query # # ;file_id=1;block_len=581
master-bin.000001 # Execute_load_query # # use `test`; load data infile '../std_data_ln/words.dat' into table t2 ;file_id=1
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; alter table t1 add b int
master-bin.000001 # Query # # use `test`; alter table t1 drop b
master-bin.000001 # Query # # use `test`; create table t3 like t1
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 select * from t3
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; replace into t1 select * from t3
master-bin.000001 # Query # # use `test`; COMMIT
drop table t1,t2,t3;
CREATE TABLE t1(a INT) ENGINE=BLACKHOLE;
INSERT DELAYED INTO t1 VALUES(1);
......
......@@ -100,6 +100,7 @@ insert into t1 values(9);
insert into t2 select * from t1;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values(9)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; insert into t2 select * from t1
......@@ -111,6 +112,7 @@ begin;
insert into t2 select * from t1;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values(10)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; insert into t2 select * from t1
......@@ -118,6 +120,7 @@ insert into t1 values(11);
commit;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values(10)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; insert into t2 select * from t1
......@@ -233,16 +236,20 @@ master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values(16)
master-bin.000001 # Query # # use `test`; insert into t1 values(18)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; delete from t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; delete from t2
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; alter table t2 engine=MyISAM
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into t1 values (1)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; insert into t2 values (20)
master-bin.000001 # Query # # use `test`; drop table t1,t2
master-bin.000001 # Query # # use `test`; create temporary table ti (a int) engine=innodb
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; insert into ti values(1)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; create temporary table t1 (a int) engine=myisam
......@@ -339,6 +346,7 @@ master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (3,3)
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t2
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4,4)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE table t2
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (5,5)
......@@ -348,6 +356,7 @@ master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE t2 (a int, b in
master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (7,7)
master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (8,8)
master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (9,9)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE table t2
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (10,10)
......@@ -503,6 +512,7 @@ insert into t2 values (bug27417(1));
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Intvar # # INSERT_ID=1
master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(1))
master-bin.000001 # Query # # use `test`; ROLLBACK
......@@ -517,6 +527,7 @@ insert into t2 select bug27417(1) union select bug27417(2);
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Intvar # # INSERT_ID=2
master-bin.000001 # Query # # use `test`; insert into t2 select bug27417(1) union select bug27417(2)
master-bin.000001 # Query # # use `test`; ROLLBACK
......@@ -544,6 +555,7 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */;
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Intvar # # INSERT_ID=6
master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */
master-bin.000001 # Query # # use `test`; ROLLBACK
......@@ -574,6 +586,7 @@ delete from t2;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Intvar # # INSERT_ID=9
master-bin.000001 # Query # # use `test`; delete from t2
master-bin.000001 # Query # # use `test`; ROLLBACK
......@@ -593,6 +606,7 @@ delete t2.* from t2,t5 where t2.a=t5.a + 1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; delete t2.* from t2,t5 where t2.a=t5.a + 1
master-bin.000001 # Query # # use `test`; ROLLBACK
select count(*) from t1 /* must be 1 */;
......@@ -612,6 +626,7 @@ count(*)
2
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Intvar # # INSERT_ID=10
master-bin.000001 # Begin_load_query # # ;file_id=1;block_len=12
master-bin.000001 # Intvar # # INSERT_ID=10
......
......@@ -15,8 +15,12 @@ COMMIT;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2)
master-bin.000001 # Query # # use `test`; UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f
......
......@@ -118,37 +118,49 @@ master-bin.000001 # Query # # create database mysqltest3
master-bin.000001 # Query # # drop database mysqltest3
master-bin.000001 # Query # # create database mysqltest3
master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))engine=innodb
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Query # # use `mysqltest2`; truncate table t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Query # # use `mysqltest2`; truncate table t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `mysqltest2`; BEGIN
master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
......
......@@ -127,7 +127,7 @@ NULL 5 10
NULL 6 12
CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3;
ERROR 23000: Duplicate entry '2' for key 'b'
SHOW BINLOG EVENTS FROM 1100;
SHOW BINLOG EVENTS FROM 1374;
Log_name Pos Event_type Server_id End_log_pos Info
CREATE TABLE t7 (a INT, b INT UNIQUE);
INSERT INTO t7 SELECT a,b FROM tt3;
......@@ -137,11 +137,11 @@ a b
1 2
2 4
3 6
SHOW BINLOG EVENTS FROM 1100;
SHOW BINLOG EVENTS FROM 1374;
Log_name Pos Event_type Server_id End_log_pos Info
# 1100 Query # 1200 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE)
# 1200 Table_map # 1242 table_id: # (test.t7)
# 1242 Write_rows # 1298 table_id: # flags: STMT_END_F
# 1374 Query # 1474 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE)
# 1474 Table_map # 1516 table_id: # (test.t7)
# 1516 Write_rows # 1572 table_id: # flags: STMT_END_F
SELECT * FROM t7 ORDER BY a,b;
a b
1 2
......@@ -154,10 +154,10 @@ INSERT INTO t7 SELECT a,b FROM tt4;
ROLLBACK;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
SHOW BINLOG EVENTS FROM 1298;
SHOW BINLOG EVENTS FROM 1572;
Log_name Pos Event_type Server_id End_log_pos Info
# 1298 Table_map # 1340 table_id: # (test.t7)
# 1340 Write_rows # 1396 table_id: # flags: STMT_END_F
# 1572 Table_map # 1614 table_id: # (test.t7)
# 1614 Write_rows # 1670 table_id: # flags: STMT_END_F
SELECT * FROM t7 ORDER BY a,b;
a b
1 2
......@@ -192,10 +192,10 @@ Create Table CREATE TABLE `t9` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW BINLOG EVENTS FROM 1396;
SHOW BINLOG EVENTS FROM 1670;
Log_name Pos Event_type Server_id End_log_pos Info
# 1396 Query # 1482 use `test`; CREATE TABLE t8 LIKE t4
# 1482 Query # 1621 use `test`; CREATE TABLE `t9` (
# 1670 Query # 1756 use `test`; CREATE TABLE t8 LIKE t4
# 1756 Query # 1895 use `test`; CREATE TABLE `t9` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
)
......@@ -398,14 +398,15 @@ SELECT * FROM t2 ORDER BY a;
a
SHOW BINLOG EVENTS FROM 637;
Log_name Pos Event_type Server_id End_log_pos Info
# 637 Query # 717 use `test`; TRUNCATE TABLE t2
# 717 Xid # 744 COMMIT /* XID */
# 744 Query # 812 use `test`; BEGIN
# 812 Table_map # 853 table_id: # (test.t2)
# 853 Write_rows # 897 table_id: # flags: STMT_END_F
# 897 Table_map # 938 table_id: # (test.t2)
# 938 Write_rows # 977 table_id: # flags: STMT_END_F
# 977 Query # 1048 use `test`; ROLLBACK
# 637 Query # 705 use `test`; BEGIN
# 705 Query # 785 use `test`; TRUNCATE TABLE t2
# 785 Xid # 812 COMMIT /* XID */
# 812 Query # 880 use `test`; BEGIN
# 880 Table_map # 921 table_id: # (test.t2)
# 921 Write_rows # 965 table_id: # flags: STMT_END_F
# 965 Table_map # 1006 table_id: # (test.t2)
# 1006 Write_rows # 1045 table_id: # flags: STMT_END_F
# 1045 Query # 1116 use `test`; ROLLBACK
SELECT * FROM t2 ORDER BY a;
a
DROP TABLE t1,t2;
......@@ -20,11 +20,13 @@ show binlog events;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=InnoDB
master-bin.000001 # Query 1 # use `test`; BEGIN
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Xid 1 # COMMIT /* XID */
master-bin.000001 # Query 1 # use `test`; drop table t1
master-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=InnoDB
master-bin.000001 # Query 1 # use `test`; BEGIN
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Xid 1 # COMMIT /* XID */
......@@ -34,10 +36,10 @@ master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_in
show binlog events from 106 limit 2;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=InnoDB
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
master-bin.000001 # Query 1 # use `test`; BEGIN
show binlog events from 106 limit 2,1;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
flush logs;
create table t3 (a int)ENGINE=InnoDB;
select * from t1 order by 1 asc;
......@@ -194,11 +196,13 @@ insert into t2 values (1);
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; 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 # # use `test`; drop table t1
master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; 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 */
......@@ -208,27 +212,30 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000002 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
master-bin.000002 # Query 1 # use `test`; create table t3 (a int)ENGINE=InnoDB
master-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=InnoDB
master-bin.000002 # Query 1 # use `test`; BEGIN
master-bin.000002 # Table_map 1 # table_id: # (test.t2)
master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000002 # Xid 1 # COMMIT /* XID */
show binary logs;
Log_name File_size
master-bin.000001 1320
master-bin.000002 406
master-bin.000001 1456
master-bin.000002 474
start slave;
show binary logs;
Log_name File_size
slave-bin.000001 1418
slave-bin.000002 307
slave-bin.000001 1536
slave-bin.000002 366
show binlog events in 'slave-bin.000001' from 4;
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000001 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4
slave-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=InnoDB
slave-bin.000001 # Query 1 # BEGIN
slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
slave-bin.000001 # Xid 1 # COMMIT /* XID */
slave-bin.000001 # Query 1 # use `test`; drop table t1
slave-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=InnoDB
slave-bin.000001 # Query 1 # BEGIN
slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
slave-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
slave-bin.000001 # Xid 1 # COMMIT /* XID */
......@@ -238,6 +245,7 @@ show binlog events in 'slave-bin.000002' from 4;
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000002 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4
slave-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=InnoDB
slave-bin.000002 # Query 1 # BEGIN
slave-bin.000002 # Table_map 1 # table_id: # (test.t2)
slave-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F
slave-bin.000002 # Xid 1 # COMMIT /* XID */
......@@ -248,7 +256,7 @@ Master_User root
Master_Port MASTER_PORT
Connect_Retry 1
Master_Log_File master-bin.000002
Read_Master_Log_Pos 406
Read_Master_Log_Pos 474
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000002
......@@ -263,7 +271,7 @@ Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 406
Exec_Master_Log_Pos 474
Relay_Log_Space #
Until_Condition None
Until_Log_File
......
......@@ -471,21 +471,27 @@ master-bin.000001 # Query # # use `mysqltest1`; insert into t1 select 'emergency
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; insert into t1 select "yesterday_24_"
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t2` (
`rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t3` (
`1` varbinary(108) NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t3)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t4` (
`a` varchar(100) DEFAULT NULL
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t4)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t5)
master-bin.000001 # Write_rows # # table_id: #
......@@ -799,21 +805,27 @@ master-bin.000001 # Query # # use `mysqltest1`; insert into t1 select 'emergency
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; insert into t1 select "yesterday_24_"
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t2` (
`rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t3` (
`1` varbinary(108) NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t3)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; BEGIN
master-bin.000001 # Query # # use `mysqltest1`; CREATE TABLE `t4` (
`a` varchar(100) DEFAULT NULL
)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t4)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `mysqltest1`; COMMIT
master-bin.000001 # Query # # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
master-bin.000001 # Table_map # # table_id: # (mysqltest1.t5)
master-bin.000001 # Write_rows # # table_id: #
......
......@@ -38,8 +38,10 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; DROP TABLE t1
......@@ -78,8 +80,10 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; DROP TABLE t1
......@@ -118,9 +122,11 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; 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 # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; DROP TABLE t1
......@@ -159,8 +165,10 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; DELETE FROM t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; DROP TABLE t1
......@@ -199,8 +207,10 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Query # # use `test`; DELETE FROM t1
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; DROP TABLE t1
......@@ -240,9 +250,11 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; 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 # # use `test`; BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
......
......@@ -72,7 +72,7 @@ CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3;
# Shouldn't be written to the binary log
--replace_column 1 # 4 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS FROM 1100;
SHOW BINLOG EVENTS FROM 1374;
# Test that INSERT-SELECT works the same way as for SBR.
CREATE TABLE t7 (a INT, b INT UNIQUE);
......@@ -82,7 +82,7 @@ SELECT * FROM t7 ORDER BY a,b;
# Should be written to the binary log
--replace_column 1 # 4 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS FROM 1100;
SHOW BINLOG EVENTS FROM 1374;
sync_slave_with_master;
SELECT * FROM t7 ORDER BY a,b;
......@@ -94,7 +94,7 @@ INSERT INTO t7 SELECT a,b FROM tt4;
ROLLBACK;
--replace_column 1 # 4 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS FROM 1298;
SHOW BINLOG EVENTS FROM 1572;
SELECT * FROM t7 ORDER BY a,b;
sync_slave_with_master;
SELECT * FROM t7 ORDER BY a,b;
......@@ -110,7 +110,7 @@ CREATE TEMPORARY TABLE tt7 SELECT 1;
--query_vertical SHOW CREATE TABLE t9
--replace_column 1 # 4 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS FROM 1396;
SHOW BINLOG EVENTS FROM 1670;
sync_slave_with_master;
--echo **** On Slave ****
--query_vertical SHOW CREATE TABLE t8
......
......@@ -22,11 +22,11 @@ from mysql.ndb_apply_status;
show binlog events from <start_pos> limit 1;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 <start_pos> Query 1 # use `test`; insert into t1 values (1,2)
master-bin.000001 <start_pos> Query 1 # use `test`; BEGIN
show binlog events from <start_pos> limit 1,1;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Xid 1 445 COMMIT /* XID */
master-bin.000001 # Query 1 486 use `test`; insert into t1 values (1,2)
begin;
insert into t1 values (2,3);
......
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;
CREATE TABLE tndb (a int) ENGINE = NDB;
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
SHOW CREATE TABLE tndb;
Table Create Table
tndb CREATE TABLE `tndb` (
`a` int(11) DEFAULT NULL
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
==== Test 1: Non-XA Engines ====
--- on master ---
SET AUTOCOMMIT = 1;
INSERT INTO tndb VALUES (1);
INSERT INTO tmyisam VALUES (1);
BEGIN;
INSERT INTO tndb VALUES (2);
INSERT INTO tndb VALUES (3);
COMMIT;
BEGIN;
INSERT INTO tmyisam VALUES (2);
INSERT INTO tmyisam VALUES (3);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (4);
INSERT INTO tmyisam VALUES (4);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (5);
INSERT INTO tndb VALUES (6);
ROLLBACK;
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
BEGIN;
INSERT INTO tndb VALUES (7);
INSERT INTO tmyisam VALUES (7);
ROLLBACK;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
SELECT * FROM tndb ORDER BY a;
a
1
2
3
4
SELECT * FROM tmyisam ORDER BY a;
a
1
2
3
4
5
6
7
--- on slave ---
SELECT * FROM tndb ORDER BY a;
a
1
2
3
4
SELECT * FROM tmyisam ORDER BY a;
a
1
2
3
4
5
6
7
==== 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 1740
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 1579
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 #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 0
Last_SQL_Error
SELECT * FROM tinnodb ORDER BY a;
a
DROP TABLE tmyisam;
DROP TABLE tinnodb;
DROP TABLE tndb;
# 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.
source include/ndb_master-slave.inc;
source include/have_ndb.inc;
CREATE TABLE tmyisam (a int) ENGINE = MYISAM;
CREATE TABLE tinnodb (a int) ENGINE = INNODB;
CREATE TABLE tndb (a int) ENGINE = NDB;
SHOW CREATE TABLE tmyisam;
SHOW CREATE TABLE tinnodb;
SHOW CREATE TABLE tndb;
--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 tndb VALUES (1);
INSERT INTO tmyisam VALUES (1);
BEGIN;
INSERT INTO tndb VALUES (2);
INSERT INTO tndb VALUES (3);
COMMIT;
BEGIN;
INSERT INTO tmyisam VALUES (2);
INSERT INTO tmyisam VALUES (3);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (4);
INSERT INTO tmyisam VALUES (4);
COMMIT;
BEGIN;
INSERT INTO tndb VALUES (5);
INSERT INTO tndb VALUES (6);
ROLLBACK;
BEGIN;
INSERT INTO tmyisam VALUES (5);
INSERT INTO tmyisam VALUES (6);
--warning 1196
ROLLBACK;
BEGIN;
INSERT INTO tndb VALUES (7);
INSERT INTO tmyisam VALUES (7);
--warning 1196
ROLLBACK;
SELECT * FROM tndb ORDER BY a;
SELECT * FROM tmyisam ORDER BY a;
--echo --- on slave ---
--sync_slave_with_master
SELECT * FROM tndb ORDER BY a;
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
DROP TABLE tmyisam;
DROP TABLE tinnodb;
DROP TABLE tndb;
......@@ -1402,6 +1402,21 @@ static int binlog_prepare(handlerton *hton, 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 hton The binlog handlerton.
@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(handlerton *hton, THD *thd, bool all)
{
DBUG_ENTER("binlog_commit");
......@@ -1414,7 +1429,15 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
trx_data->reset();
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)
......@@ -1428,6 +1451,23 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
}
}
/**
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 hton The binlog handlerton.
@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(handlerton *hton, THD *thd, bool all)
{
DBUG_ENTER("binlog_rollback");
......@@ -3967,9 +4007,11 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
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_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
......@@ -3990,32 +4032,42 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
if (my_b_tell(cache) > 0)
{
/*
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;
DBUG_EXECUTE_IF("crash_before_writing_xid",
{
if ((write_error= write_cache(cache, false, true)))
DBUG_PRINT("info", ("error writing binlog cache: %d",
write_error));
DBUG_PRINT("info", ("crashing before writing xid"));
abort();
});
if ((write_error= write_cache(cache, false, false)))
goto err;
......
......@@ -4292,6 +4292,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, (uchar*) &xid, sizeof(xid));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment