1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

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/t/rpl_transaction-master.opt:
  BitKeeper file /home/sven/bk/b26395-autocommit-xa/5.0-rpl/mysql-test/t/rpl_transaction-master.opt
mysql-test/t/rpl_transaction-slave.opt:
  BitKeeper file /home/sven/bk/b26395-autocommit-xa/5.0-rpl/mysql-test/t/rpl_transaction-slave.opt
mysql-test/r/mix_innodb_myisam_binlog.result:
  Updated result file
mysql-test/r/multi_update.result:
  Updated result file
mysql-test/r/rpl_transaction.result:
  New result file for new test case.
mysql-test/r/sp_trans_log.result:
  Updated result file
mysql-test/r/variables-big.result:
  Updated result file
mysql-test/t/rpl_transaction.test:
  New test case.
sql/log.cc:
   - Always write BEGIN and COMMIT around statements, even in autocommit
     mode.
   - Added comments for binlog_commit and binlog_rollback.
sql/log_event.cc:
  Added debug trigger to avoid writing xid events to the binlog.
This commit is contained in:
unknown
2007-12-21 20:30:23 +01:00
parent 590350633c
commit b5d95f021f
10 changed files with 331 additions and 73 deletions

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
--innodb --debug=d,do_not_write_xid

View File

@ -0,0 +1 @@
--innodb

View File

@ -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;