diff --git a/mysql-test/extra/rpl_tests/rpl_blackhole.test b/mysql-test/extra/rpl_tests/rpl_blackhole.test index 1a0eeb3cf15..569a24e5252 100644 --- a/mysql-test/extra/rpl_tests/rpl_blackhole.test +++ b/mysql-test/extra/rpl_tests/rpl_blackhole.test @@ -11,7 +11,7 @@ # executing statement. If difference is >0, then something was # written to the binary log on the slave. -connection slave; +# On Connection Slave let $before = query_get_value("SHOW MASTER STATUS", Position, 1); --echo [on master] diff --git a/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test b/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test new file mode 100644 index 00000000000..f3fdc915080 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test @@ -0,0 +1,97 @@ +# PURPOSE. Test that blackhole works with replication in all three +# modes: STATEMENT, MIXED, and ROW. +# +# METHOD. We start by creating a table on the master and then change +# the engine to use blackhole on the slave. +# +# After insert/update/delete of one or more rows, the test the +# proceeds to check that replication is running after replicating an +# change, that the blackhole engine does not contain anything (which +# is just a check that the correct engine is used), and that something +# is written to the binary log. +# +# Whe check INSERT, UPDATE, and DELETE statement for tables with no +# key (forcing a range search on the slave), primary keys (using a +# primary key lookup), and index/key with multiple matches (forcing an +# index search). + +# We start with no primary key +CREATE TABLE t1 (a INT, b INT, c INT); +CREATE TABLE t2 (a INT, b INT, c INT); + +sync_slave_with_master; +ALTER TABLE t1 ENGINE=BLACKHOLE; + +connection master; +INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4); +sync_slave_with_master; + +# Test insert, no primary key +let $statement = INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4); +source extra/rpl_tests/rpl_blackhole.test; + +# Test update, no primary key +let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1; +source extra/rpl_tests/rpl_blackhole.test; + +# Test delete, no primary key +let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 1; +source extra/rpl_tests/rpl_blackhole.test; + +# Test INSERT-SELECT into Blackhole, no primary key +let $statement = INSERT INTO t1 SELECT * FROM t2; +source extra/rpl_tests/rpl_blackhole.test; + +# +# The MASTER has MyISAM as the engine for both tables. The SLAVE has Blackhole +# on t1 (transactional engine) and MyISAM on t2 (non-transactional engine). +# +# In MIXED mode, the command "INSERT INTO t2 SELECT * FROM t1" is logged as +# statement on the master. On the slave, it is tagged as unsafe because the +# statement mixes both transactional and non-transactional engines and as such +# its changes are logged as rows. However, due to the nature of the blackhole +# engine, no rows are returned and thus any chain replication would make the +# next master on the chain diverge. +# +# Fo this reason, we have disabled the statement. +# +# Test INSERT-SELECT from Blackhole, no primary key +# let $statement = INSERT INTO t2 SELECT * FROM t1; +# source extra/rpl_tests/rpl_blackhole.test; +# + +connection master; +ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b); +sync_slave_with_master; + +# Test insert, primary key +let $statement = INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4); +source extra/rpl_tests/rpl_blackhole.test; + +# Test update, primary key +let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2; +source extra/rpl_tests/rpl_blackhole.test; + +# Test delete, primary key +let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 2; +source extra/rpl_tests/rpl_blackhole.test; + +connection master; +ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a); +sync_slave_with_master; + +# Test insert, key +let $statement = INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4); +source extra/rpl_tests/rpl_blackhole.test; + +# Test update, key +let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3; +source extra/rpl_tests/rpl_blackhole.test; + +# Test delete, key +let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 3; +source extra/rpl_tests/rpl_blackhole.test; + +connection master; +DROP TABLE t1,t2; +sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result b/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result new file mode 100644 index 00000000000..20ca37322dc --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result @@ -0,0 +1,434 @@ +include/master-slave.inc +[connection master] +SET timestamp=1000000000; +RESET MASTER; +SET timestamp=1000000000; +RESET MASTER; +CREATE TABLE t1 (a INT, b INT, c INT); +CREATE TABLE t2 (a INT, b INT, c INT); +ALTER TABLE t1 ENGINE=BLACKHOLE; +INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4); +[on master] +INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4); +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +DELETE FROM t1 WHERE a % 2 = 0 AND b = 1; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +INSERT INTO t1 SELECT * FROM t2; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b); +[on master] +INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4); +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +DELETE FROM t1 WHERE a % 2 = 0 AND b = 2; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a); +[on master] +INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4); +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +[on master] +DELETE FROM t1 WHERE a % 2 = 0 AND b = 3; +[on slave] +# Expect 0 +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +>>> Something was written to binary log <<< +DROP TABLE t1,t2; +FLUSH LOGS; +show binlog events in 'slave-bin.000001' from ; +Log_name Pos Event_type Server_id End_log_pos Info +slave-bin.000001 # Gtid_list 2 # [] +slave-bin.000001 # Binlog_checkpoint 2 # slave-bin.000001 +slave-bin.000001 # Gtid 1 # GTID 0-1-1 +slave-bin.000001 # Query 1 # use `test`; CREATE TABLE t1 (a INT, b INT, c INT) +slave-bin.000001 # Gtid 1 # GTID 0-1-2 +slave-bin.000001 # Query 1 # use `test`; CREATE TABLE t2 (a INT, b INT, c INT) +slave-bin.000001 # Gtid 2 # GTID 0-2-3 +slave-bin.000001 # Query 2 # use `test`; ALTER TABLE t1 ENGINE=BLACKHOLE +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-3 +slave-bin.000001 # Annotate_rows 1 # INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4) +slave-bin.000001 # Table_map 1 # table_id: # (test.t2) +slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-4 +slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4) +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-5 +slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-6 +slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 1 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-7 +slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 SELECT * FROM t2 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # GTID 0-1-8 +slave-bin.000001 # Query 1 # use `test`; ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b) +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-9 +slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4) +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-10 +slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-11 +slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 2 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # GTID 0-1-12 +slave-bin.000001 # Query 1 # use `test`; ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a) +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-13 +slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4) +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-14 +slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-15 +slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 3 +slave-bin.000001 # Table_map 1 # table_id: # (test.t1) +slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F +slave-bin.000001 # Query 1 # COMMIT +slave-bin.000001 # Gtid 1 # GTID 0-1-16 +slave-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */ +slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4 +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup +ROLLBACK/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Gtid list [] +# at # +#010909 4:46:40 server id # end_log_pos # Binlog checkpoint slave-bin.000001 +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-1 ddl +/*!100101 SET @@session.skip_parallel_replication=0*//*!*/; +/*!100001 SET @@session.gtid_domain_id=0*//*!*/; +/*!100001 SET @@session.server_id=1*//*!*/; +/*!100001 SET @@session.gtid_seq_no=1*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +use `test`/*!*/; +SET TIMESTAMP=1000000000/*!*/; +SET @@session.pseudo_thread_id=#/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; +SET @@session.sql_mode=1342177280/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C latin1 *//*!*/; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +CREATE TABLE t1 (a INT, b INT, c INT) +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-2 ddl +/*!100001 SET @@session.gtid_seq_no=2*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +CREATE TABLE t2 (a INT, b INT, c INT) +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-2-3 ddl +/*!100001 SET @@session.server_id=2*//*!*/; +/*!100001 SET @@session.gtid_seq_no=3*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +ALTER TABLE t1 ENGINE=BLACKHOLE +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-3 trans +/*!100001 SET @@session.server_id=1*//*!*/; +/*!100001 SET @@session.gtid_seq_no=3*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4) +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t2` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-4 trans +/*!100001 SET @@session.gtid_seq_no=4*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4) +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-5 trans +/*!100001 SET @@session.gtid_seq_no=5*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-6 trans +/*!100001 SET @@session.gtid_seq_no=6*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 1 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-7 trans +/*!100001 SET @@session.gtid_seq_no=7*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> INSERT INTO t1 SELECT * FROM t2 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-8 ddl +/*!100001 SET @@session.gtid_seq_no=8*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b) +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-9 trans +/*!100001 SET @@session.gtid_seq_no=9*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4) +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-10 trans +/*!100001 SET @@session.gtid_seq_no=10*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-11 trans +/*!100001 SET @@session.gtid_seq_no=11*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 2 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-12 ddl +/*!100001 SET @@session.gtid_seq_no=12*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a) +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-13 trans +/*!100001 SET @@session.gtid_seq_no=13*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4) +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-14 trans +/*!100001 SET @@session.gtid_seq_no=14*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-15 trans +/*!100001 SET @@session.gtid_seq_no=15*//*!*/; +BEGIN +/*!*/; +# at # +# at # +#010909 4:46:40 server id # end_log_pos # Annotate_rows: +#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 3 +#010909 4:46:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # GTID 0-1-16 ddl +/*!100001 SET @@session.gtid_seq_no=16*//*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */ +/*!*/; +# at # +#010909 4:46:40 server id # end_log_pos # Rotate to slave-bin.000002 pos: 4 +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_blackhole.test b/mysql-test/suite/rpl/t/rpl_blackhole.test index 76b2e2421c9..9128382d12b 100644 --- a/mysql-test/suite/rpl/t/rpl_blackhole.test +++ b/mysql-test/suite/rpl/t/rpl_blackhole.test @@ -20,81 +20,6 @@ source include/master-slave.inc; call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); -# We start with no primary key -CREATE TABLE t1 (a INT, b INT, c INT); -CREATE TABLE t2 (a INT, b INT, c INT); +source extra/rpl_tests/rpl_blackhole_basic.test; -sync_slave_with_master; -ALTER TABLE t1 ENGINE=BLACKHOLE; - -connection master; -INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4); -sync_slave_with_master; - -# Test insert, no primary key -let $statement = INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4); -source extra/rpl_tests/rpl_blackhole.test; - -# Test update, no primary key -let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1; -source extra/rpl_tests/rpl_blackhole.test; - -# Test delete, no primary key -let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 1; -source extra/rpl_tests/rpl_blackhole.test; - -# Test INSERT-SELECT into Blackhole, no primary key -let $statement = INSERT INTO t1 SELECT * FROM t2; -source extra/rpl_tests/rpl_blackhole.test; - -# -# The MASTER has MyISAM as the engine for both tables. The SLAVE has Blackhole -# on t1 (transactional engine) and MyISAM on t2 (non-transactional engine). -# -# In MIXED mode, the command "INSERT INTO t2 SELECT * FROM t1" is logged as -# statement on the master. On the slave, it is tagged as unsafe because the -# statement mixes both transactional and non-transactional engines and as such -# its changes are logged as rows. However, due to the nature of the blackhole -# engine, no rows are returned and thus any chain replication would make the -# next master on the chain diverge. -# -# Fo this reason, we have disabled the statement. -# -# Test INSERT-SELECT from Blackhole, no primary key -# let $statement = INSERT INTO t2 SELECT * FROM t1; -# source extra/rpl_tests/rpl_blackhole.test; -# - -connection master; -ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b); - -# Test insert, primary key -let $statement = INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4); -source extra/rpl_tests/rpl_blackhole.test; - -# Test update, primary key -let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2; -source extra/rpl_tests/rpl_blackhole.test; - -# Test delete, primary key -let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 2; -source extra/rpl_tests/rpl_blackhole.test; - -connection master; -ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a); - -# Test insert, key -let $statement = INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4); -source extra/rpl_tests/rpl_blackhole.test; - -# Test update, key -let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3; -source extra/rpl_tests/rpl_blackhole.test; - -# Test delete, key -let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 3; -source extra/rpl_tests/rpl_blackhole.test; - -connection master; -DROP TABLE t1,t2; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt new file mode 100644 index 00000000000..91302791099 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt @@ -0,0 +1 @@ +--binlog_annotate_row_events --timezone=GMT-3 diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt new file mode 100644 index 00000000000..7ac6a84faa7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt @@ -0,0 +1 @@ +--binlog_annotate_row_events --replicate_annotate_row_events diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test new file mode 100644 index 00000000000..77384d91475 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test @@ -0,0 +1,49 @@ +# ==== Purpose ==== +# +# Test verifies that when "replicate_annotate_row_events" are enabled on slave +# the DML operations on blackhole engine will be successful. It also ensures +# that Annotate events are logged into slave's binary log. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Enable "replicate_annotate_row_events" on slave and do DML operations +# on master. +# 1 - Slave server will successfully apply the DML operations and it is in +# sync with master. +# 2 - Verify that the "show binlog events" prints all annotate events. +# 3 - Stream the slave's binary log using "mysqlbinlog" tool and verify +# that the Annotate events are being displayed. +# +# ==== References ==== +# +# MDEV-11094: Blackhole table updates on slave fail when row annotation is +# enabled + +source include/have_blackhole.inc; +source include/have_binlog_format_row.inc; +source include/binlog_start_pos.inc; +source include/master-slave.inc; + +SET timestamp=1000000000; +RESET MASTER; +connection slave; +SET timestamp=1000000000; +RESET MASTER; + +connection master; +source extra/rpl_tests/rpl_blackhole_basic.test; + +# Verify on slave. +connection slave; +FLUSH LOGS; +--replace_column 2 # 5 # +--replace_result $binlog_start_pos +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval show binlog events in 'slave-bin.000001' from $binlog_start_pos + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ +--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/slave-bin.000001 + +source include/rpl_end.inc; diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 01aaa9ea15f..43bcdc541a1 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -25,6 +25,16 @@ #include "ha_blackhole.h" #include "sql_class.h" // THD, SYSTEM_THREAD_SLAVE_SQL +static bool is_row_based_replication(THD *thd) +{ + /* + A row event which has its thd->query() == NULL or a row event which has + replicate_annotate_row_events enabled. In the later case the thd->query() + will be pointing to the query, received through replicated annotate event + from master. + */ + return ((thd->query() == NULL) || thd->variables.binlog_annotate_row_events); +} /* Static declarations for handlerton */ static handler *blackhole_create_handler(handlerton *hton, @@ -109,7 +119,8 @@ int ha_blackhole::update_row(const uchar *old_data, uchar *new_data) { DBUG_ENTER("ha_blackhole::update_row"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } @@ -118,7 +129,8 @@ int ha_blackhole::delete_row(const uchar *buf) { DBUG_ENTER("ha_blackhole::delete_row"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } @@ -135,7 +147,8 @@ int ha_blackhole::rnd_next(uchar *buf) int rc; DBUG_ENTER("ha_blackhole::rnd_next"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) rc= 0; else rc= HA_ERR_END_OF_FILE; @@ -220,7 +233,8 @@ int ha_blackhole::index_read_map(uchar * buf, const uchar * key, int rc; DBUG_ENTER("ha_blackhole::index_read"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) rc= 0; else rc= HA_ERR_END_OF_FILE; @@ -235,7 +249,8 @@ int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key, int rc; DBUG_ENTER("ha_blackhole::index_read_idx"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) rc= 0; else rc= HA_ERR_END_OF_FILE; @@ -249,7 +264,8 @@ int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key, int rc; DBUG_ENTER("ha_blackhole::index_read_last"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + is_row_based_replication(thd)) rc= 0; else rc= HA_ERR_END_OF_FILE;