List:Commits« Previous MessageNext Message »
From:Luis Soares Date:February 22 2010 10:46pm
Subject:bzr commit into mysql-5.1-bugteam branch (luis.soares:3341) Bug#51226
View as plain text  
#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
Thread
bzr commit into mysql-5.1-bugteam branch (luis.soares:3341) Bug#51226Luis Soares22 Feb
  • Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3341)Bug#51226Alfranio Correia2 Mar
    • Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3341)Bug#51226Luís Soares3 Mar
Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3341)Bug#51226Luís Soares3 Mar
Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3341)Bug#51226Luís Soares3 Mar