#At file:///home/lsoares/Workspace/bzr/work/bugfixing/51226/mysql-5.1-bugteam/ based on revid:joro@stripped
3341 Luis Soares 2010-02-22
BUG#51226: mysqlbinlog replay: ERROR 1146 when using temp tables
+ failing statements
This is a small regression from BUG@35583 which happens in a very
particular situation. Consider two connections con1 and con2,
where their pseudo_thread_ids are 1 and 2 respectively. Both
connections create a temporary table with the same name, say
t1. On both connections several statements are executing
concurrently, so their events (lets use E1 to identify an event
from con1 and E2 for an event from con2) end up in the binary log
inter-leaved. Now, picture the case that we have the following
sequence: E1,E2,S*1; in which S*1 is a failing statement in
con1. Furthermore, assume that after S*1, con1 disconnects and an
implicit 'drop temp table t1' is written to the binary log,
before any other event from con2 is logged. This causes the
implicit drop event to be logged without the proper
pseudo_thread_id=1, thence when replaying the binary log, the
drop would be executed under the assumption that it had been
originally processed under con2.
This happens because right before starting execution of S*1 the
thread context is reset, and consequently the
thread_specific_used flag is unset (note: this is one of the
flags that transitively controls logging and printing of
pseudo_thread_id in the event header). Since S*1 fails and right
after the connection is be dropped, the thread_specific_used flag
would remain unset, the pseudo_thread_id would therefore not be
logged.
This scenario only happens for the case that we have: E1,E2,S*1
followed by a disconnection. If we had a successful statement
executed on con1 before S*1 (E1,E2,E1,S*1 followed by
disconnection), there would not be a problem, as the correct
pseudo_thread_id would have been logged before S*1.
We fix this by setting thread_specific_used whenever we are
binlogging a DROP in close_temporary_tables, and resetting it to
its previous value afterward.
modified:
mysql-test/suite/binlog/r/binlog_tmp_table.result
mysql-test/suite/binlog/t/binlog_tmp_table.test
sql/sql_base.cc
=== modified file 'mysql-test/suite/binlog/r/binlog_tmp_table.result'
--- a/mysql-test/suite/binlog/r/binlog_tmp_table.result 2009-09-07 05:42:54 +0000
+++ b/mysql-test/suite/binlog/r/binlog_tmp_table.result 2010-02-22 22:46:10 +0000
@@ -29,3 +29,14 @@ a
6
8
drop table foo;
+RESET MASTER;
+create database b51226;
+use b51226;
+create temporary table t1(i int);
+use b51226;
+create temporary table t1(i int);
+create temporary table t1(i int);
+ERROR 42S01: Table 't1' already exists
+insert into t1 values(1);
+DROP DATABASE b51226;
+FLUSH LOGS;
=== modified file 'mysql-test/suite/binlog/t/binlog_tmp_table.test'
--- a/mysql-test/suite/binlog/t/binlog_tmp_table.test 2009-09-07 05:42:54 +0000
+++ b/mysql-test/suite/binlog/t/binlog_tmp_table.test 2010-02-22 22:46:10 +0000
@@ -82,3 +82,69 @@ select * from foo;
# clean up
drop table foo;
+
+#################################################################
+# BUG#51226
+#################################################################
+
+RESET MASTER;
+
+-- let $dbname=b51226
+
+connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+connect (con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+
+#
+# action: on con1 create the database and the tmp table
+#
+-- connection con1
+-- eval create database $dbname
+-- eval use $dbname
+create temporary table t1(i int);
+
+#
+# action: on con1 create the tmp table
+#
+-- connection con2
+-- eval use $dbname
+create temporary table t1(i int);
+
+# action: at this point, the last event binlogged contains the
+# pseudo_thread_id from con2. So now we switch to con1, issue
+# a statement that fails and close the connection (which logs
+# implicitely a DROP TEMPORARY TABLE).
+#
+# Before the patch this would not log con1's pseudo_thread_id
+# because the failing statement would reset THD context
+# (unsetting the thread_specific_used flag, and consequently,
+# causing the DROP event to be logged without pseudo_thread_id
+# in its header).
+
+-- connection con1
+-- error 1050
+create temporary table t1(i int);
+-- disconnect con1
+
+-- connection default
+-- let $wait_binlog_event= DROP
+-- source include/wait_for_binlog_event.inc
+
+# action: insert in the t1. This would cause the the test to fail,
+# because when replaying the binlog the previous implicit drop
+# temp table would have been executed under the wrong
+# pseudo_thread_id, dropping the tmp table on con2.
+-- connection con2
+insert into t1 values(1);
+-- disconnect con2
+
+-- connection default
+-- let $wait_binlog_event= DROP
+-- source include/wait_for_binlog_event.inc
+
+-- eval DROP DATABASE $dbname
+FLUSH LOGS;
+
+# assertion: assert that when replaying the binary log will succeed,
+# instead of failing with "Table 'XXX.YYY' doesn't exist"
+-- let $MYSQLD_DATADIR= `select @@datadir`
+-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-01-27 13:10:53 +0000
+++ b/sql/sql_base.cc 2010-02-22 22:46:10 +0000
@@ -1515,6 +1515,7 @@ void close_temporary_tables(THD *thd)
{
if (is_user_table(table))
{
+ bool save_thread_specific_used= thd->thread_specific_used;
my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id;
/* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
@@ -1544,6 +1545,7 @@ void close_temporary_tables(THD *thd)
thd->clear_error();
CHARSET_INFO *cs_save= thd->variables.character_set_client;
thd->variables.character_set_client= system_charset_info;
+ thd->thread_specific_used= TRUE;
Query_log_event qinfo(thd, s_query.ptr(),
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE, 0);
@@ -1556,6 +1558,7 @@ void close_temporary_tables(THD *thd)
"Failed to write the DROP statement for temporary tables to binary log");
}
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
+ thd->thread_specific_used= save_thread_specific_used;
}
else
{
Attachment: [text/bzr-bundle] bzr/luis.soares@sun.com-20100222224610-0au4hvs9yp0q626g.bundle