summaryrefslogtreecommitdiff
path: root/mysql-test
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2003-10-29 14:23:35 +0100
committerunknown <guilhem@mysql.com>2003-10-29 14:23:35 +0100
commit03dbf8ccbb649825d7aafd9f00234bee35111de9 (patch)
treefce8da3a99c175419b43436ce7e5ca6b3d7c8618 /mysql-test
parente0fd80f72a9583581bcce0755e179f44dfe580a9 (diff)
downloadmariadb-git-03dbf8ccbb649825d7aafd9f00234bee35111de9.tar.gz
Fix for BUG#1686
"If 2 master threads with same-name temp table, slave makes bad binlog" and (two birds with one stone) for BUG#1240 "slave of slave breaks when STOP SLAVE was issud on parent slave and temp tables". Here is the design change: in a slave running with --log-slave-updates, events are now logged with the thread id they had on the master. So no more id conflicts between master threads, but introduces id conflicts between one master thread and one normal client thread connected to the slave. This is solved by storing the server id in the temp table's name. New test which requires mysql-test-run to be run with --manager, otherwise it will be skipped. Undoing a Monty's change (hum, a chill runs down my spine ;) which was "Cleanup temporary tables when slave ends" in ChangeSet 1.1572.1.1. mysql-test/mysql-test-run.sh: One new test which needs more than one slave so must be hardcoded in mysql-test-run.sh. sql/log_event.cc: The event needs to carry a slave_proxy_id (which is set at event's creation and used at event's logging). This is used for events created by ::exec_event() in the slave SQL thread: now we want to log these events with the thread id they had on the master. This is so that several same-name temp tables simultaneously created on the master end up with not the same thread id in the slave's binlog. sql/log_event.h: Query and Load need to carry a slave_proxy_id, like they carried a thread_id (to replicate temp tables well). sql/slave.cc: Do not free temp tables in the slave SQL thread. Or they will be lost when one does STOP SLAVE / START SLAVE. We even save them in rli->save_temporary_tables and set thd->temporary_tables=0 to prevent them to be freed. sql/sql_base.cc: Put the server id in the table cache key name for temp tables (we already put the slave_proxy_id, but we also need the server id in case normal clients (not slave threads) are using temp tables on the slave). sql/unireg.h: 4 more bytes, to store the server id.
Diffstat (limited to 'mysql-test')
-rw-r--r--mysql-test/mysql-test-run.sh2
-rw-r--r--mysql-test/r/rpl_chain_temp_table.result30
-rw-r--r--mysql-test/t/rpl_chain_temp_table.test89
3 files changed, 120 insertions, 1 deletions
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 6cba5eecddd..d155c02c652 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -1161,7 +1161,7 @@ run_testcase ()
echo $tname > $CURRENT_TEST
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ $USE_MANAGER = 1 ] ; then
- many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
+ many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)`
fi
if [ -n "$SKIP_TEST" ] ; then
diff --git a/mysql-test/r/rpl_chain_temp_table.result b/mysql-test/r/rpl_chain_temp_table.result
new file mode 100644
index 00000000000..5ece80565c7
--- /dev/null
+++ b/mysql-test/r/rpl_chain_temp_table.result
@@ -0,0 +1,30 @@
+slave stop;
+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;
+slave start;
+reset master;
+change master to master_host='127.0.0.1',master_port=9307, master_user='root';
+start slave;
+create temporary table t1 (a int);
+create temporary table t1 (a int);
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 2
+create temporary table t1 (a int);
+create temporary table t1 (a int);
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 4
+stop slave;
+insert into t1 values(1);
+create table t2 as select * from t1;
+start slave;
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 4
+select * from t2;
+a
+1
+drop table t2;
diff --git a/mysql-test/t/rpl_chain_temp_table.test b/mysql-test/t/rpl_chain_temp_table.test
new file mode 100644
index 00000000000..65701d8a078
--- /dev/null
+++ b/mysql-test/t/rpl_chain_temp_table.test
@@ -0,0 +1,89 @@
+ # This test makes some assumptions about values of thread ids, which should be
+# true if the servers have been restarted for this test. So we want to
+# stop/restart servers. Note that if assumptions are wrong, the test will not
+# fail; it will just fail to test the error-prone scenario.
+# Using the manager is the only way to have more than one slave server.
+
+require_manager;
+server_stop master;
+server_start master;
+server_stop slave;
+server_start slave;
+# no need for slave_sec (no assumptions on thread ids for this server).
+
+source include/master-slave.inc;
+connect (slave_sec,localhost,root,,test,0,slave.sock-1);
+connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+reset master;
+save_master_pos;
+connection slave_sec;
+eval change master to master_host='127.0.0.1',master_port=$SLAVE_MYPORT, master_user='root';
+start slave;
+sync_with_master;
+
+# :P now we have a chain ready-to-test.
+
+connection master;
+create temporary table t1 (a int);
+save_master_pos;
+connection slave;
+sync_with_master;
+connection master1;
+create temporary table t1 (a int);
+save_master_pos;
+connection slave;
+sync_with_master;
+save_master_pos;
+
+# First test:
+
+connection slave_sec;
+# Before BUG#1686 ("If 2 master threads with same-name temp table, slave makes
+# bad binlog") was fixed, sync_with_master failed
+sync_with_master;
+show status like 'slave_open_temp_tables';
+
+# 'master' and 'master1' usually have thread id 2-3 or 3-4.
+# 'slave' and 'slave1' usually have thread id 2-3.
+connection slave;
+create temporary table t1 (a int);
+connection slave1;
+create temporary table t1 (a int);
+# So it's likely that in the binlog of slave we get
+# server_id=of_master thread_id=3 create temp...
+# server_id=of_slave thread_id=3 create temp...
+# which would confuse slave-sec unless slave-sec uses server id to distinguish
+# between temp tables (here thread id is obviously not enough to distinguish).
+
+save_master_pos;
+
+# Second test:
+
+connection slave_sec;
+# If we did not use the server id to distinguish between temp tables,
+# sync_with_master would fail
+sync_with_master;
+show status like 'slave_open_temp_tables';
+
+# Third test (BUG#1240 "slave of slave breaks when STOP SLAVE was issud on
+# parent slave and temp tables").
+stop slave;
+connection slave;
+insert into t1 values(1);
+create table t2 as select * from t1;
+save_master_pos;
+connection slave_sec;
+start slave;
+sync_with_master;
+show status like 'slave_open_temp_tables';
+select * from t2;
+
+# clean up
+connection slave;
+drop table t2;
+save_master_pos;
+connection slave_sec;
+sync_with_master;