Browse Source
BUG#12691 (Exec_master_log_pos corrupted with SQL_SLAVE_SKIP_COUNTER):
BUG#12691 (Exec_master_log_pos corrupted with SQL_SLAVE_SKIP_COUNTER):
Adding code to keep skipping events while inside a transaction. Execution
will start just after the transaction has been skipped.
sql/slave.cc:
Adding code to set the thd->options flag for the slave SQL thread
even when BEGIN, ROLLBACK, COMMIT, and XID events are being skipped.
Adding code to not decrease the slave skip counter from 1 to 0 if we
are inside a transaction. This will keep the counter at 1, and keep
skipping events, until a transaction terminator is read. At that point,
the slave skip counter will be decreased to 0, and events will be read
and executed instead of read and skipped.
mysql-test/r/rpl_slave_skip.result:
New BitKeeper file ``mysql-test/r/rpl_slave_skip.result''
mysql-test/t/rpl_slave_skip-slave.opt:
New BitKeeper file ``mysql-test/t/rpl_slave_skip-slave.opt''
mysql-test/t/rpl_slave_skip.test:
New BitKeeper file ``mysql-test/t/rpl_slave_skip.test''
pull/374/head
4 changed files with 401 additions and 3 deletions
-
144mysql-test/r/rpl_slave_skip.result
-
1mysql-test/t/rpl_slave_skip-slave.opt
-
203mysql-test/t/rpl_slave_skip.test
-
56sql/slave.cc
@ -0,0 +1,144 @@ |
|||
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; |
|||
**** On Master **** |
|||
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB; |
|||
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM; |
|||
==== Skipping normal transactions ==== |
|||
**** On Slave **** |
|||
STOP SLAVE; |
|||
**** On Master **** |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, 'master,slave'); |
|||
INSERT INTO t1 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, 'master,slave'); |
|||
COMMIT; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
1 master |
|||
2 master |
|||
3 master |
|||
4 master,slave |
|||
5 master,slave |
|||
6 master,slave |
|||
**** On Slave **** |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
4 master,slave |
|||
5 master,slave |
|||
6 master,slave |
|||
**** On Master **** |
|||
DELETE FROM t1; |
|||
==== Skipping two normal transactions ==== |
|||
**** On Slave **** |
|||
STOP SLAVE; |
|||
**** On Master **** |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, 'master'); |
|||
INSERT INTO t1 VALUES (5, 'master'); |
|||
INSERT INTO t1 VALUES (6, 'master'); |
|||
COMMIT; |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (7, 'master,slave'); |
|||
INSERT INTO t1 VALUES (8, 'master,slave'); |
|||
INSERT INTO t1 VALUES (9, 'master,slave'); |
|||
COMMIT; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
1 master |
|||
2 master |
|||
3 master |
|||
4 master |
|||
5 master |
|||
6 master |
|||
7 master,slave |
|||
8 master,slave |
|||
9 master,slave |
|||
**** On Slave **** |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8; |
|||
START SLAVE; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
7 master,slave |
|||
8 master,slave |
|||
9 master,slave |
|||
**** On Master **** |
|||
DELETE FROM t1; |
|||
==== Skipping without autocommit ==== |
|||
**** On Slave **** |
|||
STOP SLAVE; |
|||
**** On Master **** |
|||
SET AUTOCOMMIT=0; |
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
INSERT INTO t1 VALUES (4, 'master,slave'); |
|||
INSERT INTO t1 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, 'master,slave'); |
|||
COMMIT; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
1 master |
|||
2 master |
|||
3 master |
|||
4 master,slave |
|||
5 master,slave |
|||
6 master,slave |
|||
**** On Slave **** |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
4 master,slave |
|||
5 master,slave |
|||
6 master,slave |
|||
==== Rollback of transaction with non-transactional change ==== |
|||
**** On Master **** |
|||
DELETE FROM t1; |
|||
SET AUTOCOMMIT=1; |
|||
**** On Slave **** |
|||
STOP SLAVE; |
|||
**** On Master **** |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, ''); |
|||
INSERT INTO t2 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, ''); |
|||
ROLLBACK; |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, ''); |
|||
INSERT INTO t2 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, ''); |
|||
ROLLBACK; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
SELECT * FROM t2 ORDER BY a; |
|||
a b |
|||
2 master |
|||
5 master,slave |
|||
**** On Slave **** |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
a b |
|||
SELECT * FROM t2 ORDER BY a; |
|||
a b |
|||
5 master,slave |
|||
==== Cleanup ==== |
|||
**** On Master **** |
|||
DROP TABLE t1, t2; |
|||
@ -0,0 +1 @@ |
|||
--innodb |
|||
@ -0,0 +1,203 @@ |
|||
source include/have_innodb.inc; |
|||
source include/master-slave.inc; |
|||
|
|||
# This test is for checking that the use of SQL_SLAVE_SKIP_COUNTER |
|||
# behaves as expected, i.e., that it is guaranteed to skip an entire |
|||
# group and not start executing in the middle of a transaction. |
|||
|
|||
# We are checking the correct behaviour when using both a |
|||
# transactional and non-transactional table. The non-transactional |
|||
# table comes into play when rolling back a transaction containing a |
|||
# write to this table. In that case, the transaction should still be |
|||
# written to the binary log, and the slave will apply it and then roll |
|||
# it back to get the non-transactional change into the table. |
|||
|
|||
--echo **** On Master **** |
|||
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB; |
|||
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM; |
|||
|
|||
--echo ==== Skipping normal transactions ==== |
|||
|
|||
--echo **** On Slave **** |
|||
sync_slave_with_master; |
|||
STOP SLAVE; |
|||
source include/wait_for_slave_to_stop.inc; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, 'master,slave'); |
|||
INSERT INTO t1 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, 'master,slave'); |
|||
COMMIT; |
|||
|
|||
save_master_pos; |
|||
|
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
# This will skip a begin event and the first INSERT of the |
|||
# transaction, and it should keep skipping until it has reached the |
|||
# transaction terminator. |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
source include/wait_for_slave_to_start.inc; |
|||
sync_with_master; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
DELETE FROM t1; |
|||
sync_slave_with_master; |
|||
|
|||
--echo ==== Skipping two normal transactions ==== |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
STOP SLAVE; |
|||
source include/wait_for_slave_to_stop.inc; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, 'master'); |
|||
INSERT INTO t1 VALUES (5, 'master'); |
|||
INSERT INTO t1 VALUES (6, 'master'); |
|||
COMMIT; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (7, 'master,slave'); |
|||
INSERT INTO t1 VALUES (8, 'master,slave'); |
|||
INSERT INTO t1 VALUES (9, 'master,slave'); |
|||
COMMIT; |
|||
|
|||
save_master_pos; |
|||
|
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
# This will skip a begin event and the first INSERT of the |
|||
# transaction, and it should keep skipping until it has reached the |
|||
# transaction terminator. |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8; |
|||
START SLAVE; |
|||
source include/wait_for_slave_to_start.inc; |
|||
sync_with_master; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
DELETE FROM t1; |
|||
sync_slave_with_master; |
|||
|
|||
--echo ==== Skipping without autocommit ==== |
|||
|
|||
# Testing without using autocommit instead. It should still write a |
|||
# BEGIN event, so the behaviour should be the same |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
STOP SLAVE; |
|||
source include/wait_for_slave_to_stop.inc; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
SET AUTOCOMMIT=0; |
|||
|
|||
INSERT INTO t1 VALUES (1, 'master'); |
|||
INSERT INTO t1 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, 'master'); |
|||
COMMIT; |
|||
|
|||
INSERT INTO t1 VALUES (4, 'master,slave'); |
|||
INSERT INTO t1 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, 'master,slave'); |
|||
COMMIT; |
|||
|
|||
save_master_pos; |
|||
|
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
# This will skip a begin event and the first INSERT of the |
|||
# transaction, and it should keep skipping until it has reached the |
|||
# transaction terminator. |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
source include/wait_for_slave_to_start.inc; |
|||
sync_with_master; |
|||
SELECT * FROM t1 ORDER BY a; |
|||
|
|||
# Testing with a non-transactional table in the transaction. This will |
|||
# log a ROLLBACK as a transaction terminator, which is a normal Query |
|||
# log event. |
|||
|
|||
--echo ==== Rollback of transaction with non-transactional change ==== |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
DELETE FROM t1; |
|||
SET AUTOCOMMIT=1; |
|||
|
|||
--echo **** On Slave **** |
|||
sync_slave_with_master; |
|||
STOP SLAVE; |
|||
source include/wait_for_slave_to_stop.inc; |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
disable_warnings; |
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (1, ''); |
|||
INSERT INTO t2 VALUES (2, 'master'); |
|||
INSERT INTO t1 VALUES (3, ''); |
|||
ROLLBACK; |
|||
|
|||
BEGIN; |
|||
INSERT INTO t1 VALUES (4, ''); |
|||
INSERT INTO t2 VALUES (5, 'master,slave'); |
|||
INSERT INTO t1 VALUES (6, ''); |
|||
ROLLBACK; |
|||
enable_warnings; |
|||
|
|||
save_master_pos; |
|||
|
|||
SELECT * FROM t1 ORDER BY a; |
|||
SELECT * FROM t2 ORDER BY a; |
|||
|
|||
--echo **** On Slave **** |
|||
connection slave; |
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; |
|||
START SLAVE; |
|||
source include/wait_for_slave_to_start.inc; |
|||
sync_with_master; |
|||
|
|||
SELECT * FROM t1 ORDER BY a; |
|||
SELECT * FROM t2 ORDER BY a; |
|||
|
|||
--echo ==== Cleanup ==== |
|||
|
|||
--echo **** On Master **** |
|||
connection master; |
|||
DROP TABLE t1, t2; |
|||
sync_slave_with_master; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue