mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
BUG#28618 (Skipping into the middle of a group with SQL_SLAVE_SKIP_COUNTER
is possible): When skipping the beginning of a transaction starting with BEGIN, the OPTION_BEGIN flag was not set correctly, which caused the slave to not recognize that it was inside a group. This patch sets the OPTION_BEGIN flag for BEGIN, COMMIT, ROLLBACK, and XID events. It also adds checks if inside a group before decreasing the slave skip counter to zero. Begin_query_log_event was not marked that it could not end a group, which is now corrected.
This commit is contained in:
@ -736,7 +736,7 @@ connection slave;
|
|||||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||||
--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 #
|
--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 #
|
||||||
--query_vertical SHOW SLAVE STATUS
|
--query_vertical SHOW SLAVE STATUS
|
||||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
|
|
||||||
--echo *** Try to insert in master ****
|
--echo *** Try to insert in master ****
|
||||||
@ -744,6 +744,8 @@ connection master;
|
|||||||
INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2);
|
INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2);
|
||||||
SELECT * FROM t15 ORDER BY c1;
|
SELECT * FROM t15 ORDER BY c1;
|
||||||
|
|
||||||
|
#SHOW BINLOG EVENTS;
|
||||||
|
|
||||||
--echo *** Try to select from slave ****
|
--echo *** Try to select from slave ****
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
--replace_column 7 CURRENT_TIMESTAMP
|
--replace_column 7 CURRENT_TIMESTAMP
|
||||||
|
3
mysql-test/suite/rpl/data/rpl_bug28618.dat
Normal file
3
mysql-test/suite/rpl/data/rpl_bug28618.dat
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
1|master only
|
||||||
|
2|master only
|
||||||
|
3|master only
|
@ -142,3 +142,211 @@ Last_SQL_Errno 0
|
|||||||
Last_SQL_Error
|
Last_SQL_Error
|
||||||
**** On Master ****
|
**** On Master ****
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
SET SESSION BINLOG_FORMAT=ROW;
|
||||||
|
SET AUTOCOMMIT=0;
|
||||||
|
CREATE TABLE t1 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
CREATE TABLE t2 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
CREATE TABLE t3 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
INSERT INTO t1 VALUES (1,'master/slave');
|
||||||
|
INSERT INTO t2 VALUES (1,'master/slave');
|
||||||
|
INSERT INTO t3 VALUES (1,'master/slave');
|
||||||
|
CREATE TRIGGER tr1 AFTER UPDATE on t1 FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO t2 VALUES (NEW.a,NEW.b);
|
||||||
|
DELETE FROM t2 WHERE a < NEW.a;
|
||||||
|
END|
|
||||||
|
CREATE TRIGGER tr2 AFTER INSERT on t2 FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE t3 SET a =2, b = 'master only';
|
||||||
|
END|
|
||||||
|
**** On Slave ****
|
||||||
|
STOP SLAVE;
|
||||||
|
**** On Master ****
|
||||||
|
UPDATE t1 SET a = 2, b = 'master only' WHERE a = 1;
|
||||||
|
DROP TRIGGER tr1;
|
||||||
|
DROP TRIGGER tr2;
|
||||||
|
INSERT INTO t1 VALUES (3,'master/slave');
|
||||||
|
INSERT INTO t2 VALUES (3,'master/slave');
|
||||||
|
INSERT INTO t3 VALUES (3,'master/slave');
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t2 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t3 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
*** On Slave ***
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 master/slave
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t2 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 master/slave
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t3 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 master/slave
|
||||||
|
3 master/slave
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
|
**** Case 2: Row binlog format and transactional tables ****
|
||||||
|
*** On Master ***
|
||||||
|
CREATE TABLE t4 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
CREATE TABLE t5 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
CREATE TABLE t6 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
**** On Slave ****
|
||||||
|
STOP SLAVE;
|
||||||
|
*** On Master ***
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (2, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (2, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (2, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (3, 'master/slave');
|
||||||
|
INSERT INTO t5 VALUES (3, 'master/slave');
|
||||||
|
INSERT INTO t6 VALUES (3, 'master/slave');
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
*** On Slave ***
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
**** On Slave ****
|
||||||
|
STOP SLAVE;
|
||||||
|
*** On Master ***
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (6, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (6, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (6, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (7, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (7, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (7, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
*** On Slave ***
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=10;
|
||||||
|
START SLAVE;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
STOP SLAVE;
|
||||||
|
SET AUTOCOMMIT=0;
|
||||||
|
INSERT INTO t4 VALUES (4, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (4, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (4, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
INSERT INTO t4 VALUES (5, 'master/slave');
|
||||||
|
INSERT INTO t5 VALUES (5, 'master/slave');
|
||||||
|
INSERT INTO t6 VALUES (5, 'master/slave');
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
4 master only
|
||||||
|
5 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
4 master only
|
||||||
|
5 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
2 master only
|
||||||
|
3 master/slave
|
||||||
|
4 master only
|
||||||
|
5 master/slave
|
||||||
|
6 master only
|
||||||
|
7 master only
|
||||||
|
*** On Slave ***
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
5 master/slave
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
5 master/slave
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
a b
|
||||||
|
3 master/slave
|
||||||
|
5 master/slave
|
||||||
|
DROP TABLE t4, t5, t6;
|
||||||
|
**** Case 3: Statement logging format and LOAD DATA with non-transactional table ****
|
||||||
|
*** On Master ***
|
||||||
|
CREATE TABLE t10 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
*** On Slave ***
|
||||||
|
STOP SLAVE;
|
||||||
|
*** On Master ***
|
||||||
|
SET SESSION BINLOG_FORMAT=STATEMENT;
|
||||||
|
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/rpl_bug28618.dat' INTO TABLE t10 FIELDS TERMINATED BY '|';
|
||||||
|
SELECT * FROM t10 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 master only
|
||||||
|
2 master only
|
||||||
|
3 master only
|
||||||
|
*** On Slave ***
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
SELECT * FROM t10 ORDER BY a;
|
||||||
|
a b
|
||||||
|
DROP TABLE t10;
|
||||||
|
1
mysql-test/suite/rpl/t/rpl_slave_skip-slave.opt
Normal file
1
mysql-test/suite/rpl/t/rpl_slave_skip-slave.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb
|
@ -1,7 +1,9 @@
|
|||||||
source include/master-slave.inc;
|
source include/master-slave.inc;
|
||||||
|
source include/have_innodb.inc;
|
||||||
|
|
||||||
--echo **** On Slave ****
|
--echo **** On Slave ****
|
||||||
connection slave;
|
connection slave;
|
||||||
|
source include/have_innodb.inc;
|
||||||
STOP SLAVE;
|
STOP SLAVE;
|
||||||
|
|
||||||
--echo **** On Master ****
|
--echo **** On Master ****
|
||||||
@ -69,3 +71,240 @@ query_vertical SHOW SLAVE STATUS;
|
|||||||
connection master;
|
connection master;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
#
|
||||||
|
# More tests for BUG#28618
|
||||||
|
#
|
||||||
|
# Case 1.
|
||||||
|
# ROW binlog format and non-transactional tables.
|
||||||
|
# Create the group of events via triggers and try to skip
|
||||||
|
# some items of that group.
|
||||||
|
#
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
SET SESSION BINLOG_FORMAT=ROW;
|
||||||
|
SET AUTOCOMMIT=0;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
CREATE TABLE t2 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
CREATE TABLE t3 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1,'master/slave');
|
||||||
|
INSERT INTO t2 VALUES (1,'master/slave');
|
||||||
|
INSERT INTO t3 VALUES (1,'master/slave');
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr1 AFTER UPDATE on t1 FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO t2 VALUES (NEW.a,NEW.b);
|
||||||
|
DELETE FROM t2 WHERE a < NEW.a;
|
||||||
|
END|
|
||||||
|
|
||||||
|
CREATE TRIGGER tr2 AFTER INSERT on t2 FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE t3 SET a =2, b = 'master only';
|
||||||
|
END|
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
--echo **** On Slave ****
|
||||||
|
sync_slave_with_master;
|
||||||
|
STOP SLAVE;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
|
||||||
|
--echo **** On Master ****
|
||||||
|
connection master;
|
||||||
|
UPDATE t1 SET a = 2, b = 'master only' WHERE a = 1;
|
||||||
|
DROP TRIGGER tr1;
|
||||||
|
DROP TRIGGER tr2;
|
||||||
|
INSERT INTO t1 VALUES (3,'master/slave');
|
||||||
|
INSERT INTO t2 VALUES (3,'master/slave');
|
||||||
|
INSERT INTO t3 VALUES (3,'master/slave');
|
||||||
|
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
SELECT * FROM t2 ORDER BY a;
|
||||||
|
SELECT * FROM t3 ORDER BY a;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
connection slave;
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
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;
|
||||||
|
SELECT * FROM t3 ORDER BY a;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
--echo **** Case 2: Row binlog format and transactional tables ****
|
||||||
|
|
||||||
|
# Create the transaction and try to skip some
|
||||||
|
# queries from one.
|
||||||
|
|
||||||
|
--echo *** On Master ***
|
||||||
|
connection master;
|
||||||
|
CREATE TABLE t4 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
CREATE TABLE t5 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
CREATE TABLE t6 (a INT, b VARCHAR(20)) ENGINE=innodb;
|
||||||
|
|
||||||
|
--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 t4 VALUES (2, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (2, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (2, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (3, 'master/slave');
|
||||||
|
INSERT INTO t5 VALUES (3, 'master/slave');
|
||||||
|
INSERT INTO t6 VALUES (3, 'master/slave');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
connection slave;
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
source include/wait_for_slave_to_start.inc;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
# Test skipping two groups
|
||||||
|
|
||||||
|
--echo **** On Slave ****
|
||||||
|
connection slave;
|
||||||
|
STOP SLAVE;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
|
||||||
|
--echo *** On Master ***
|
||||||
|
connection master;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (6, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (6, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (6, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 VALUES (7, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (7, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (7, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
connection slave;
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=10;
|
||||||
|
START SLAVE;
|
||||||
|
source include/wait_for_slave_to_start.inc;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
#
|
||||||
|
# And the same, but with autocommit = 0
|
||||||
|
#
|
||||||
|
connection slave;
|
||||||
|
STOP SLAVE;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
SET AUTOCOMMIT=0;
|
||||||
|
|
||||||
|
INSERT INTO t4 VALUES (4, 'master only');
|
||||||
|
INSERT INTO t5 VALUES (4, 'master only');
|
||||||
|
INSERT INTO t6 VALUES (4, 'master only');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
INSERT INTO t4 VALUES (5, 'master/slave');
|
||||||
|
INSERT INTO t5 VALUES (5, 'master/slave');
|
||||||
|
INSERT INTO t6 VALUES (5, 'master/slave');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
connection slave;
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
source include/wait_for_slave_to_start.inc;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
SELECT * FROM t4 ORDER BY a;
|
||||||
|
SELECT * FROM t5 ORDER BY a;
|
||||||
|
SELECT * FROM t6 ORDER BY a;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t4, t5, t6;
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
--echo **** Case 3: Statement logging format and LOAD DATA with non-transactional table ****
|
||||||
|
|
||||||
|
# LOAD DATA creates two events in binary log for statement binlog format.
|
||||||
|
# Try to skip the first.
|
||||||
|
|
||||||
|
--echo *** On Master ***
|
||||||
|
connection master;
|
||||||
|
CREATE TABLE t10 (a INT, b VARCHAR(20)) ENGINE=myisam;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
sync_slave_with_master;
|
||||||
|
STOP SLAVE;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
|
||||||
|
--echo *** On Master ***
|
||||||
|
connection master;
|
||||||
|
SET SESSION BINLOG_FORMAT=STATEMENT;
|
||||||
|
exec cp ./suite/rpl/data/rpl_bug28618.dat $MYSQLTEST_VARDIR/tmp/;
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/rpl_bug28618.dat' INTO TABLE t10 FIELDS TERMINATED BY '|';
|
||||||
|
remove_file $MYSQLTEST_VARDIR/tmp/rpl_bug28618.dat;
|
||||||
|
|
||||||
|
SELECT * FROM t10 ORDER BY a;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
|
||||||
|
--echo *** On Slave ***
|
||||||
|
connection slave;
|
||||||
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
|
START SLAVE;
|
||||||
|
source include/wait_for_slave_to_start.inc;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
SELECT * FROM t10 ORDER BY a;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t10;
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
@ -707,7 +707,7 @@ Last_IO_Errno #
|
|||||||
Last_IO_Error #
|
Last_IO_Error #
|
||||||
Last_SQL_Errno 1060
|
Last_SQL_Errno 1060
|
||||||
Last_SQL_Error Error 'Duplicate column name 'c6'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5'
|
Last_SQL_Error Error 'Duplicate column name 'c6'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5'
|
||||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
*** Try to insert in master ****
|
*** Try to insert in master ****
|
||||||
INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2);
|
INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2);
|
||||||
|
@ -570,7 +570,8 @@ Log_event::do_shall_skip(Relay_log_info *rli)
|
|||||||
(ulong) server_id, (ulong) ::server_id,
|
(ulong) server_id, (ulong) ::server_id,
|
||||||
rli->replicate_same_server_id,
|
rli->replicate_same_server_id,
|
||||||
rli->slave_skip_counter));
|
rli->slave_skip_counter));
|
||||||
if (server_id == ::server_id && !rli->replicate_same_server_id)
|
if (server_id == ::server_id && !rli->replicate_same_server_id ||
|
||||||
|
rli->slave_skip_counter == 1 && rli->is_in_group())
|
||||||
return EVENT_SKIP_IGNORE;
|
return EVENT_SKIP_IGNORE;
|
||||||
else if (rli->slave_skip_counter > 0)
|
else if (rli->slave_skip_counter > 0)
|
||||||
return EVENT_SKIP_COUNT;
|
return EVENT_SKIP_COUNT;
|
||||||
@ -1227,6 +1228,16 @@ void Log_event::print_timestamp(IO_CACHE* file, time_t* ts)
|
|||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
|
inline Log_event::enum_skip_reason
|
||||||
|
Log_event::continue_group(Relay_log_info *rli)
|
||||||
|
{
|
||||||
|
if (rli->slave_skip_counter == 1)
|
||||||
|
return Log_event::EVENT_SKIP_IGNORE;
|
||||||
|
return Log_event::do_shall_skip(rli);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Query_log_event methods
|
Query_log_event methods
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@ -2235,6 +2246,30 @@ int Query_log_event::do_update_pos(Relay_log_info *rli)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Log_event::enum_skip_reason
|
||||||
|
Query_log_event::do_shall_skip(Relay_log_info *rli)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Query_log_event::do_shall_skip");
|
||||||
|
DBUG_PRINT("debug", ("query: %s; q_len: %d", query, q_len));
|
||||||
|
DBUG_ASSERT(query && q_len > 0);
|
||||||
|
|
||||||
|
if (rli->slave_skip_counter > 0)
|
||||||
|
{
|
||||||
|
if (strcmp("BEGIN", query) == 0)
|
||||||
|
{
|
||||||
|
thd->options|= OPTION_BEGIN;
|
||||||
|
DBUG_RETURN(Log_event::continue_group(rli));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0)
|
||||||
|
{
|
||||||
|
thd->options&= ~OPTION_BEGIN;
|
||||||
|
DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(Log_event::do_shall_skip(rli));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -3871,10 +3906,7 @@ Intvar_log_event::do_shall_skip(Relay_log_info *rli)
|
|||||||
that we do not change the value of the slave skip counter since it
|
that we do not change the value of the slave skip counter since it
|
||||||
will be decreased by the following insert event.
|
will be decreased by the following insert event.
|
||||||
*/
|
*/
|
||||||
if (rli->slave_skip_counter == 1)
|
return continue_group(rli);
|
||||||
return Log_event::EVENT_SKIP_IGNORE;
|
|
||||||
else
|
|
||||||
return Log_event::do_shall_skip(rli);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -3970,10 +4002,7 @@ Rand_log_event::do_shall_skip(Relay_log_info *rli)
|
|||||||
that we do not change the value of the slave skip counter since it
|
that we do not change the value of the slave skip counter since it
|
||||||
will be decreased by the following insert event.
|
will be decreased by the following insert event.
|
||||||
*/
|
*/
|
||||||
if (rli->slave_skip_counter == 1)
|
return continue_group(rli);
|
||||||
return Log_event::EVENT_SKIP_IGNORE;
|
|
||||||
else
|
|
||||||
return Log_event::do_shall_skip(rli);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !MYSQL_CLIENT */
|
#endif /* !MYSQL_CLIENT */
|
||||||
@ -4049,6 +4078,17 @@ int Xid_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
"COMMIT /* implicit, from Xid_log_event */");
|
"COMMIT /* implicit, from Xid_log_event */");
|
||||||
return end_trans(thd, COMMIT);
|
return end_trans(thd, COMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log_event::enum_skip_reason
|
||||||
|
Xid_log_event::do_shall_skip(Relay_log_info *rli)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Xid_log_event::do_shall_skip");
|
||||||
|
if (rli->slave_skip_counter > 0) {
|
||||||
|
thd->options&= ~OPTION_BEGIN;
|
||||||
|
DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(Log_event::do_shall_skip(rli));
|
||||||
|
}
|
||||||
#endif /* !MYSQL_CLIENT */
|
#endif /* !MYSQL_CLIENT */
|
||||||
|
|
||||||
|
|
||||||
@ -4427,10 +4467,7 @@ User_var_log_event::do_shall_skip(Relay_log_info *rli)
|
|||||||
that we do not change the value of the slave skip counter since it
|
that we do not change the value of the slave skip counter since it
|
||||||
will be decreased by the following insert event.
|
will be decreased by the following insert event.
|
||||||
*/
|
*/
|
||||||
if (rli->slave_skip_counter == 1)
|
return continue_group(rli);
|
||||||
return Log_event::EVENT_SKIP_IGNORE;
|
|
||||||
else
|
|
||||||
return Log_event::do_shall_skip(rli);
|
|
||||||
}
|
}
|
||||||
#endif /* !MYSQL_CLIENT */
|
#endif /* !MYSQL_CLIENT */
|
||||||
|
|
||||||
@ -5366,6 +5403,19 @@ int Begin_load_query_log_event::get_create_or_append() const
|
|||||||
#endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
|
#endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
|
Log_event::enum_skip_reason
|
||||||
|
Begin_load_query_log_event::do_shall_skip(Relay_log_info *rli)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If the slave skip counter is 1, then we should not start executing
|
||||||
|
on the next event.
|
||||||
|
*/
|
||||||
|
return continue_group(rli);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Execute_load_query_log_event methods
|
Execute_load_query_log_event methods
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@ -6870,10 +6920,7 @@ Table_map_log_event::do_shall_skip(Relay_log_info *rli)
|
|||||||
If the slave skip counter is 1, then we should not start executing
|
If the slave skip counter is 1, then we should not start executing
|
||||||
on the next event.
|
on the next event.
|
||||||
*/
|
*/
|
||||||
if (rli->slave_skip_counter == 1)
|
return continue_group(rli);
|
||||||
return Log_event::EVENT_SKIP_IGNORE;
|
|
||||||
else
|
|
||||||
return Log_event::do_shall_skip(rli);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Table_map_log_event::do_update_pos(Relay_log_info *rli)
|
int Table_map_log_event::do_update_pos(Relay_log_info *rli)
|
||||||
|
@ -870,6 +870,25 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to ignore an event w.r.t. the slave skip counter.
|
||||||
|
|
||||||
|
This function can be used inside do_shall_skip() for functions
|
||||||
|
that cannot end a group. If the slave skip counter is 1 when
|
||||||
|
seeing such an event, the event shall be ignored, the counter
|
||||||
|
left intact, and processing continue with the next event.
|
||||||
|
|
||||||
|
A typical usage is:
|
||||||
|
@code
|
||||||
|
enum_skip_reason do_shall_skip(Relay_log_info *rli) {
|
||||||
|
return continue_group(rli);
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@return Skip reason
|
||||||
|
*/
|
||||||
|
enum_skip_reason continue_group(Relay_log_info *rli);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Primitive to apply an event to the database.
|
Primitive to apply an event to the database.
|
||||||
|
|
||||||
@ -1086,6 +1105,7 @@ public:
|
|||||||
|
|
||||||
public: /* !!! Public in this patch to allow old usage */
|
public: /* !!! Public in this patch to allow old usage */
|
||||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
|
virtual enum_skip_reason do_shall_skip(Relay_log_info *rli);
|
||||||
virtual int do_apply_event(Relay_log_info const *rli);
|
virtual int do_apply_event(Relay_log_info const *rli);
|
||||||
virtual int do_update_pos(Relay_log_info *rli);
|
virtual int do_update_pos(Relay_log_info *rli);
|
||||||
|
|
||||||
@ -1559,6 +1579,7 @@ class Xid_log_event: public Log_event
|
|||||||
private:
|
private:
|
||||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
virtual int do_apply_event(Relay_log_info const *rli);
|
virtual int do_apply_event(Relay_log_info const *rli);
|
||||||
|
enum_skip_reason do_shall_skip(Relay_log_info *rli);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1937,6 +1958,10 @@ public:
|
|||||||
*description_event);
|
*description_event);
|
||||||
~Begin_load_query_log_event() {}
|
~Begin_load_query_log_event() {}
|
||||||
Log_event_type get_type_code() { return BEGIN_LOAD_QUERY_EVENT; }
|
Log_event_type get_type_code() { return BEGIN_LOAD_QUERY_EVENT; }
|
||||||
|
private:
|
||||||
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
|
virtual enum_skip_reason do_shall_skip(Relay_log_info *rli);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,6 +365,18 @@ public:
|
|||||||
m_flags |= (1UL << flag);
|
m_flags |= (1UL << flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the value of a replication state flag.
|
||||||
|
|
||||||
|
@param flag Flag to get value of
|
||||||
|
|
||||||
|
@return @c true if the flag was set, @c false otherwise.
|
||||||
|
*/
|
||||||
|
bool get_flag(enum_state_flag flag)
|
||||||
|
{
|
||||||
|
return m_flags & (1UL << flag);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clear the value of a replication state flag.
|
Clear the value of a replication state flag.
|
||||||
|
|
||||||
|
@ -1853,10 +1853,13 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
|
|||||||
// EVENT_SKIP_NOT,
|
// EVENT_SKIP_NOT,
|
||||||
"not skipped",
|
"not skipped",
|
||||||
// EVENT_SKIP_IGNORE,
|
// EVENT_SKIP_IGNORE,
|
||||||
"skipped because event originated from this server",
|
"skipped because event should be ignored",
|
||||||
// EVENT_SKIP_COUNT
|
// EVENT_SKIP_COUNT
|
||||||
"skipped because event skip counter was non-zero"
|
"skipped because event skip counter was non-zero"
|
||||||
};
|
};
|
||||||
|
DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d",
|
||||||
|
thd->options & OPTION_BEGIN ? 1 : 0,
|
||||||
|
rli->get_flag(Relay_log_info::IN_STMT)));
|
||||||
DBUG_PRINT("skip_event", ("%s event was %s",
|
DBUG_PRINT("skip_event", ("%s event was %s",
|
||||||
ev->get_type_str(), explain[reason]));
|
ev->get_type_str(), explain[reason]));
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user