From 61d706a4f04906632e461aa6a2756429b1be9c2c Mon Sep 17 00:00:00 2001 From: Leonard Zhou Date: Mon, 23 Feb 2009 11:26:38 +0800 Subject: [PATCH] Bug#40013 mixed replication: row based format could lead to stale tmp tables on the slave. In mixed mode, if we create a temporary table and do some update which switch to ROW format, the format will keep in ROW format until the session ends or the table is dropped explicitly. When the session ends, the temp table is dropped automaticly at cleanup time. but it checks only current binlog format and so skip insertion of DROP TABLE instructions into binlog. So the temp table can't be dropped correctly at slave. Our solution is that when closing temp tables at cleanup time we check both binlog format and binlog mode, and we could write DROP TABLE instructions into binlog if current binlog format is ROW but in MIX mode. mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result: Test result file. mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test: Test file. sql/sql_base.cc: Didn't do binloging when both current format and default format are ROW. --- .../suite/rpl/r/rpl_temp_table_mix_row.result | 26 ++++++++++ .../suite/rpl/t/rpl_temp_table_mix_row.test | 49 +++++++++++++++++++ sql/sql_base.cc | 3 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result create mode 100644 mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test diff --git a/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result b/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result new file mode 100644 index 00000000000..feffefc9dad --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result @@ -0,0 +1,26 @@ +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; +==== Initialize ==== +[on master] +CREATE TABLE t1 (a CHAR(48)); +CREATE TEMPORARY TABLE t1_tmp1(a INT); +INSERT INTO t1 VALUES (UUID()); +[on slave] +==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; +Variable_name Value +Slave_open_temp_tables 1 +[on master] +[on slave] +==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; +Variable_name Value +Slave_open_temp_tables 0 +==== Clean up ==== +[on master] +DROP TABLE t1; +[on slave] diff --git a/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test new file mode 100644 index 00000000000..1fe484b7c27 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test @@ -0,0 +1,49 @@ +# ==== Purpose ==== +# +# Test that temporary tables are correctly replicated after switching to ROW format in MIX mode. +# This test case will test the condition of the bug#40013. +# The test step is: +# 1: create temp table on connection 'master'; +# 2: switch to ROW format using 'INSERT INTO t1 VALUES (UUID());' +# 3: disconnect 'master' and connect to a new connection 'master1'; +# 4: sync to slave and check the number of temp tables on slave. +# + +source include/master-slave.inc; +source include/have_binlog_format_mixed.inc; + +--echo ==== Initialize ==== + +--echo [on master] +--connection master + +CREATE TABLE t1 (a CHAR(48)); +CREATE TEMPORARY TABLE t1_tmp1(a INT); +INSERT INTO t1 VALUES (UUID()); + +--echo [on slave] +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--echo [on master] +--connection master + +disconnect master; +--connection master1 + +--echo [on slave] +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--echo ==== Clean up ==== + +--echo [on master] +--connection master1 +DROP TABLE t1; + +--echo [on slave] +sync_slave_with_master; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6db9f1df0f2..7602b1187aa 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1440,7 +1440,8 @@ void close_temporary_tables(THD *thd) if (!thd->temporary_tables) return; - if (!mysql_bin_log.is_open() || thd->current_stmt_binlog_row_based) + if (!mysql_bin_log.is_open() || + (thd->current_stmt_binlog_row_based && thd->variables.binlog_format == BINLOG_FORMAT_ROW)) { TABLE *tmp_next; for (table= thd->temporary_tables; table; table= tmp_next)