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:
1
mysql-test/t/rpl_transaction-master.opt
Normal file
1
mysql-test/t/rpl_transaction-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--innodb --debug=d,do_not_write_xid
|
1
mysql-test/t/rpl_transaction-slave.opt
Normal file
1
mysql-test/t/rpl_transaction-slave.opt
Normal file
@ -0,0 +1 @@
|
||||
--innodb
|
106
mysql-test/t/rpl_transaction.test
Normal file
106
mysql-test/t/rpl_transaction.test
Normal 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;
|
Reference in New Issue
Block a user