diff --git a/mysql-test/r/rpl_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result new file mode 100644 index 00000000000..9249405ac26 --- /dev/null +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -0,0 +1,45 @@ +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; +CREATE DATABASE test_ignore; +**** On Master **** +SHOW DATABASES; +Database +information_schema +mysql +test +test_ignore +USE test; +CREATE TABLE t1 (a INT, b INT); +SHOW TABLES; +Tables_in_test +t1 +INSERT INTO t1 VALUES (1,1), (2,2); +USE test_ignore; +CREATE TABLE t2 (a INT, b INT); +SHOW TABLES; +Tables_in_test_ignore +t2 +INSERT INTO t2 VALUES (3,3), (4,4); +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: 5.1.5-alpha-debug-log, Binlog ver: 4 +master-bin.000001 102 Query 1 195 use `test`; CREATE TABLE t1 (a INT, b INT) +master-bin.000001 195 Table_map 1 235 test.t1 +master-bin.000001 235 Write_rows 1 282 +**** On Slave **** +SHOW DATABASES; +Database +information_schema +mysql +test +USE test; +SHOW TABLES; +Tables_in_test +t1 +USE test_ignore; +ERROR 42000: Unknown database 'test_ignore' +DROP DATABASE test_ignore; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ce5c8ac67f4..e1f58970821 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -23,5 +23,6 @@ subselect : Bug#15706 type_time : Bug#15805 #rpl000002 : Bug#15920 Temporary tables are not binlogged in SBR ps_7ndb : Bug#15923 Core dump in RBR mode when executing test suite -sp_trans : Bug#15924 Code dump in RBR mode when executing test suite +#sp_trans : Bug#15924 Code dump in RBR mode when executing test suite mysqlslap : Bug#16167 + diff --git a/mysql-test/t/rpl_row_basic_11bugs-master.opt b/mysql-test/t/rpl_row_basic_11bugs-master.opt new file mode 100644 index 00000000000..d5ae999b180 --- /dev/null +++ b/mysql-test/t/rpl_row_basic_11bugs-master.opt @@ -0,0 +1 @@ +--binlog_ignore_db=test_ignore; diff --git a/mysql-test/t/rpl_row_basic_11bugs.test b/mysql-test/t/rpl_row_basic_11bugs.test new file mode 100644 index 00000000000..76ff5a581c9 --- /dev/null +++ b/mysql-test/t/rpl_row_basic_11bugs.test @@ -0,0 +1,31 @@ +--source include/have_row_based.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# Bug#15942 (RBR ignores --binlog_ignore_db and tries to map to table +# on slave for writes) + +CREATE DATABASE test_ignore; # --binlog_ignore_db=mysqltest_ignore + +--echo **** On Master **** +SHOW DATABASES; +USE test; +CREATE TABLE t1 (a INT, b INT); +SHOW TABLES; +INSERT INTO t1 VALUES (1,1), (2,2); +USE test_ignore; +CREATE TABLE t2 (a INT, b INT); +SHOW TABLES; +INSERT INTO t2 VALUES (3,3), (4,4); +SHOW BINLOG EVENTS; +sync_slave_with_master; +--echo **** On Slave **** +SHOW DATABASES; +USE test; +SHOW TABLES; +--error 1049 +USE test_ignore; + +connection master; +DROP DATABASE test_ignore; +sync_slave_with_master; diff --git a/sql/handler.cc b/sql/handler.cc index db97b14da2a..d36db3281b3 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2797,7 +2797,7 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) - Row-based replication is on - It is not a temporary table - The binlog is enabled - - The table shall be binlogged (binlog_*_db rules) [Seems disabled /Matz] + - The table shall be binlogged (binlog_*_db rules) */ #ifdef HAVE_ROW_BASED_REPLICATION @@ -2806,7 +2806,8 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) return binlog_row_based && thd && (thd->options & OPTION_BIN_LOG) && - (table->s->tmp_table == NO_TMP_TABLE); + (table->s->tmp_table == NO_TMP_TABLE) && + binlog_filter->db_ok(table->s->db.str); } template int binlog_log_row(TABLE* table, diff --git a/sql/log.cc b/sql/log.cc index 44d3869e9d5..dd08ca7b9b5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -241,13 +241,15 @@ static int binlog_savepoint_set(THD *thd, void *sv) DBUG_ENTER("binlog_savepoint_set"); binlog_trx_data *const trx_data= (binlog_trx_data*) thd->ha_data[binlog_hton.slot]; - IO_CACHE *trans_log= &trx_data->trans_log; - DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(trans_log)); + DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(&trx_data->trans_log)); - *(my_off_t *)sv= my_b_tell(trans_log); + *(my_off_t *)sv= my_b_tell(&trx_data->trans_log); /* Write it to the binary log */ - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); - DBUG_RETURN(mysql_bin_log.write(&qinfo)); + + int const error= + thd->binlog_query(THD::STMT_QUERY_TYPE, + thd->query, thd->query_length, TRUE, FALSE); + DBUG_RETURN(error); } static int binlog_savepoint_rollback(THD *thd, void *sv) @@ -265,8 +267,10 @@ static int binlog_savepoint_rollback(THD *thd, void *sv) */ if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE)) { - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); - DBUG_RETURN(mysql_bin_log.write(&qinfo)); + int const error= + thd->binlog_query(THD::STMT_QUERY_TYPE, + thd->query, thd->query_length, TRUE, FALSE); + DBUG_RETURN(error); } reinit_io_cache(trans_log, WRITE_CACHE, *(my_off_t *)sv, 0, 0); DBUG_RETURN(0); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7c6f61d6edc..3a816a62321 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1976,6 +1976,23 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->client_capabilities= client_capabilities; backup->savepoints= transaction.savepoints; + /* + For row-based replication and before executing a function/trigger, + the pending rows event has to be flushed. The function/trigger + might execute statement that require the pending event to be + flushed. A simple example: + + CREATE FUNCTION foo() RETURNS INT + BEGIN + SAVEPOINT x; + RETURN 0; + END + + INSERT INTO t1 VALUES (1), (foo()), (2); + */ + if (binlog_row_based) + thd->binlog_flush_pending_rows_event(false); + if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) && !binlog_row_based) options&= ~OPTION_BIN_LOG;