1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

MWL#234: Support for marking binlog events to not be replicated, and for telling slaves not to replicate events with such mark

This commit is contained in:
unknown
2011-08-11 11:38:52 +02:00
parent 51c7723eb2
commit c4d69f1775
13 changed files with 677 additions and 39 deletions

View File

@ -0,0 +1,162 @@
include/master-slave.inc
[connection master]
CREATE USER 'nonsuperuser'@'127.0.0.1';
GRANT ALTER,CREATE,DELETE,DROP,EVENT,INSERT,PROCESS,REPLICATION SLAVE,
SELECT,UPDATE ON *.* TO 'nonsuperuser'@'127.0.0.1';
SET GLOBAL replicate_ignore_do_not_replicate=1;
ERROR 42000: Access denied; you need the SUPER privilege for this operation
DROP USER'nonsuperuser'@'127.0.0.1';
SET GLOBAL replicate_ignore_do_not_replicate=1;
ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=1;
START SLAVE;
SET do_not_replicate=0;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
INSERT INTO t1(a) VALUES (1);
INSERT INTO t2(a) VALUES (1);
SET do_not_replicate=1;
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
INSERT INTO t1(a) VALUES (2);
INSERT INTO t2(a) VALUES (2);
FLUSH NO_WRITE_TO_BINLOG LOGS;
SHOW TABLES;
Tables_in_test
t1
t2
SELECT * FROM t1;
a b
1 NULL
SELECT * FROM t2;
a b
1 NULL
DROP TABLE t3;
FLUSH NO_WRITE_TO_BINLOG LOGS;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=0;
START SLAVE;
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
INSERT INTO t3(a) VALUES(2);
SELECT * FROM t3;
a b
2 NULL
DROP TABLE t3;
TRUNCATE t1;
RESET MASTER;
SET do_not_replicate=0;
INSERT INTO t1 VALUES (1,0);
SET do_not_replicate=1;
INSERT INTO t1 VALUES (2,0);
SET do_not_replicate=0;
INSERT INTO t1 VALUES (3,0);
SELECT * FROM t1 ORDER by a;
a b
1 0
2 0
3 0
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=1;
TRUNCATE t1;
SELECT * FROM t1 ORDER by a;
a b
1 0
2 0
3 0
START SLAVE;
SELECT * FROM t1 ORDER by a;
a b
1 0
3 0
TRUNCATE t1;
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter=2;
SET GLOBAL replicate_ignore_do_not_replicate=1;
START SLAVE;
SET @old_binlog_format= @@binlog_format;
SET binlog_format= statement;
SET do_not_replicate=0;
INSERT INTO t1 VALUES (1,5);
SET do_not_replicate=1;
INSERT INTO t1 VALUES (2,5);
SET do_not_replicate=0;
INSERT INTO t1 VALUES (3,5);
INSERT INTO t1 VALUES (4,5);
SET binlog_format= @old_binlog_format;
SELECT * FROM t1;
a b
4 5
TRUNCATE t1;
BINLOG '66I6Tg8BAAAAZgAAAGoAAAABAAQANS40LjAtTWFyaWFEQi12YWxncmluZC1tYXgtZGVidWctbG9n
AAAAAAAAAAAAAAAAAADrojpOEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC';
BINLOG 'HaM6ThMBAAAAKgAAANgAAAAAgA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
HaM6ThcBAAAAJgAAAP4AAAAAgA8AAAAAAAEAAv/8AQAAAAgAAAA=';
BINLOG 'JqM6ThMBAAAAKgAAALEBAAAAAA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
JqM6ThcBAAAAJgAAANcBAAAAAA8AAAAAAAEAAv/8AgAAAAgAAAA=';
SELECT * FROM t1 ORDER BY a;
a b
1 8
2 8
SELECT * FROM t1 ORDER by a;
a b
2 8
SET do_not_replicate=0;
BEGIN;
SET do_not_replicate=0;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SET do_not_replicate=1;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
ROLLBACK;
SET do_not_replicate=1;
BEGIN;
SET do_not_replicate=0;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SET do_not_replicate=1;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
COMMIT;
SET autocommit=0;
INSERT INTO t2(a) VALUES(100);
SET do_not_replicate=1;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
ROLLBACK;
SET autocommit=1;
SET do_not_replicate=1;
CREATE FUNCTION foo (x INT) RETURNS INT BEGIN SET SESSION do_not_replicate=x; RETURN x; END|
CREATE PROCEDURE bar(x INT) BEGIN SET SESSION do_not_replicate=x; END|
CREATE FUNCTION baz (x INT) RETURNS INT BEGIN CALL bar(x); RETURN x; END|
SELECT foo(0);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT baz(0);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SET @a= foo(1);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SET @a= baz(1);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
UPDATE t2 SET b=foo(0);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
UPDATE t2 SET b=baz(0);
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
INSERT INTO t1 VALUES (101, foo(1));
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
INSERT INTO t1 VALUES (101, baz(0));
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT @@do_not_replicate;
@@do_not_replicate
1
CALL bar(0);
SELECT @@do_not_replicate;
@@do_not_replicate
0
CALL bar(1);
SELECT @@do_not_replicate;
@@do_not_replicate
1
DROP FUNCTION foo;
DROP PROCEDURE bar;
DROP FUNCTION baz;
SET do_not_replicate=0;
DROP TABLE t1,t2;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=0;
START SLAVE;
include/rpl_end.inc

View File

@ -0,0 +1,245 @@
--source include/master-slave.inc
--source include/have_innodb.inc
connection slave;
# Test that SUPER is required to change @@replicate_ignore_do_not_replicate.
CREATE USER 'nonsuperuser'@'127.0.0.1';
GRANT ALTER,CREATE,DELETE,DROP,EVENT,INSERT,PROCESS,REPLICATION SLAVE,
SELECT,UPDATE ON *.* TO 'nonsuperuser'@'127.0.0.1';
connect(nonpriv, 127.0.0.1, nonsuperuser,, test, $SLAVE_MYPORT,);
connection nonpriv;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET GLOBAL replicate_ignore_do_not_replicate=1;
disconnect nonpriv;
connection slave;
DROP USER'nonsuperuser'@'127.0.0.1';
--error ER_SLAVE_MUST_STOP
SET GLOBAL replicate_ignore_do_not_replicate=1;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=1;
START SLAVE;
connection master;
SET do_not_replicate=0;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
INSERT INTO t1(a) VALUES (1);
INSERT INTO t2(a) VALUES (1);
SET do_not_replicate=1;
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
INSERT INTO t1(a) VALUES (2);
INSERT INTO t2(a) VALUES (2);
# Inject a rotate event in the binlog stream sent to slave (otherwise we will
# fail sync_slave_with_master as the last event on the master is not present
# on the slave).
FLUSH NO_WRITE_TO_BINLOG LOGS;
sync_slave_with_master;
connection slave;
SHOW TABLES;
SELECT * FROM t1;
SELECT * FROM t2;
connection master;
DROP TABLE t3;
FLUSH NO_WRITE_TO_BINLOG LOGS;
sync_slave_with_master;
connection slave;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=0;
START SLAVE;
connection master;
CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
INSERT INTO t3(a) VALUES(2);
sync_slave_with_master;
connection slave;
SELECT * FROM t3;
connection master;
DROP TABLE t3;
#
# Test that the slave will preserve the @@do_not_replicate flag in its
# own binlog.
#
TRUNCATE t1;
sync_slave_with_master;
connection slave;
RESET MASTER;
connection master;
SET do_not_replicate=0;
INSERT INTO t1 VALUES (1,0);
SET do_not_replicate=1;
INSERT INTO t1 VALUES (2,0);
SET do_not_replicate=0;
INSERT INTO t1 VALUES (3,0);
sync_slave_with_master;
connection slave;
# Since slave has @@replicate_ignore_do_not_replicate=0, it should have
# applied all events.
SELECT * FROM t1 ORDER by a;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=1;
let $SLAVE_DATADIR= `select @@datadir`;
connection master;
TRUNCATE t1;
# Now apply the slave binlog to the master, to check that both the slave
# and mysqlbinlog will preserve the @@do_not_replicate flag.
--exec $MYSQL_BINLOG $SLAVE_DATADIR/slave-bin.000001 > $MYSQLTEST_VARDIR/tmp/rpl_do_not_replicate.binlog
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/rpl_do_not_replicate.binlog
# The master should have all three events.
SELECT * FROM t1 ORDER by a;
# The slave should be missing event 2, which is marked with the
# @@do_not_replicate flag.
connection slave;
START SLAVE;
connection master;
sync_slave_with_master;
connection slave;
SELECT * FROM t1 ORDER by a;
#
# Test that @@sql_slave_skip_counter does not count skipped @@do_not_replicate
# events.
#
connection master;
TRUNCATE t1;
sync_slave_with_master;
connection slave;
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter=2;
SET GLOBAL replicate_ignore_do_not_replicate=1;
START SLAVE;
connection master;
# Need to fix @@binlog_format to get consistent event count.
SET @old_binlog_format= @@binlog_format;
SET binlog_format= statement;
SET do_not_replicate=0;
INSERT INTO t1 VALUES (1,5);
SET do_not_replicate=1;
INSERT INTO t1 VALUES (2,5);
SET do_not_replicate=0;
INSERT INTO t1 VALUES (3,5);
INSERT INTO t1 VALUES (4,5);
SET binlog_format= @old_binlog_format;
sync_slave_with_master;
connection slave;
# The slave should have skipped the first three inserts (number 1 and 3 due
# to @@sql_slave_skip_counter=2, number 2 due to
# @@replicate_ignore_do_not_replicate=1). So only number 4 should be left.
SELECT * FROM t1;
#
# Check that BINLOG statement preserves the @@do_not_replicate flag.
#
connection master;
TRUNCATE t1;
# Format description log event.
BINLOG '66I6Tg8BAAAAZgAAAGoAAAABAAQANS40LjAtTWFyaWFEQi12YWxncmluZC1tYXgtZGVidWctbG9n
AAAAAAAAAAAAAAAAAADrojpOEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC';
# INSERT INTO t1 VALUES (1,8) # with @@do_not_replicate=1
BINLOG 'HaM6ThMBAAAAKgAAANgAAAAAgA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
HaM6ThcBAAAAJgAAAP4AAAAAgA8AAAAAAAEAAv/8AQAAAAgAAAA=';
# INSERT INTO t1 VALUES (2,8) # with @@do_not_replicate=0
BINLOG 'JqM6ThMBAAAAKgAAALEBAAAAAA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
JqM6ThcBAAAAJgAAANcBAAAAAA8AAAAAAAEAAv/8AgAAAAgAAAA=';
SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
# Slave should have only the second insert, the first should be ignored due to
# the @@do_not_replicate flag.
SELECT * FROM t1 ORDER by a;
# Test that it is not possible to d change @@do_not_replicate inside a
# transaction or statement, thereby replicating only parts of statements
# or transactions.
connection master;
SET do_not_replicate=0;
BEGIN;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET do_not_replicate=0;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET do_not_replicate=1;
ROLLBACK;
SET do_not_replicate=1;
BEGIN;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET do_not_replicate=0;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET do_not_replicate=1;
COMMIT;
SET autocommit=0;
INSERT INTO t2(a) VALUES(100);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET do_not_replicate=1;
ROLLBACK;
SET autocommit=1;
SET do_not_replicate=1;
--delimiter |
CREATE FUNCTION foo (x INT) RETURNS INT BEGIN SET SESSION do_not_replicate=x; RETURN x; END|
CREATE PROCEDURE bar(x INT) BEGIN SET SESSION do_not_replicate=x; END|
CREATE FUNCTION baz (x INT) RETURNS INT BEGIN CALL bar(x); RETURN x; END|
--delimiter ;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SELECT foo(0);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SELECT baz(0);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET @a= foo(1);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
SET @a= baz(1);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
UPDATE t2 SET b=foo(0);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
UPDATE t2 SET b=baz(0);
--error ER_LOCK_OR_ACTIVE_TRANSACTION
INSERT INTO t1 VALUES (101, foo(1));
--error ER_LOCK_OR_ACTIVE_TRANSACTION
INSERT INTO t1 VALUES (101, baz(0));
SELECT @@do_not_replicate;
CALL bar(0);
SELECT @@do_not_replicate;
CALL bar(1);
SELECT @@do_not_replicate;
DROP FUNCTION foo;
DROP PROCEDURE bar;
DROP FUNCTION baz;
# Clean up.
connection master;
SET do_not_replicate=0;
DROP TABLE t1,t2;
connection slave;
STOP SLAVE;
SET GLOBAL replicate_ignore_do_not_replicate=0;
START SLAVE;
--source include/rpl_end.inc