List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:July 11 2010 7:36pm
Subject:bzr commit into mysql-trunk-bugfixing branch (alfranio.correia:3087)
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql.new/bzrwork/bug-53452/mysql-trunk-bugfixing/ based on revid:alfranio.correia@stripped

 3087 Alfranio Correia	2010-07-11
      (no message)

    modified:
      sql/log.cc
      sql/log_event.cc
      sql/sql_class.cc
      sql/sql_lex.h
=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-07-09 09:05:17 +0000
+++ b/sql/log.cc	2010-07-11 19:35:51 +0000
@@ -209,7 +209,7 @@ class binlog_cache_data
 {
 public:
   binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
-  incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE)
+  incident(FALSE)
   {
     cache_log.end_of_file= max_binlog_cache_size;
   }
@@ -245,20 +245,9 @@ public:
     return(incident);
   }
 
-  void set_changes_to_non_trans_temp_table()
-  {
-    changes_to_non_trans_temp_table_flag= TRUE;    
-  }
-
-  bool changes_to_non_trans_temp_table()
-  {
-    return (changes_to_non_trans_temp_table_flag);    
-  }
-
   void reset()
   {
     truncate(0);
-    changes_to_non_trans_temp_table_flag= FALSE;
     incident= FALSE;
     before_stmt_pos= MY_OFF_T_UNDEF;
     cache_log.end_of_file= max_binlog_cache_size;
@@ -316,12 +305,6 @@ private:
   bool incident;
 
   /*
-    This flag indicates if the cache has changes to temporary tables.
-    @TODO This a temporary fix and should be removed after BUG#54562.
-  */
-  bool changes_to_non_trans_temp_table_flag;
-
-  /*
     It truncates the cache to a certain position. This includes deleting the
     pending event.
    */
@@ -1801,8 +1784,6 @@ static int binlog_rollback(handlerton *h
         ((thd->variables.option_bits & OPTION_KEEP_LOG) ||
          (trans_has_updated_non_trans_table(thd) &&
           thd->variables.binlog_format == BINLOG_FORMAT_STMT) ||
-         (cache_mngr->trx_cache.changes_to_non_trans_temp_table() &&
-          thd->variables.binlog_format == BINLOG_FORMAT_MIXED) ||
          (trans_has_updated_non_trans_table(thd) &&
           ending_single_stmt_trans(thd,all) &&
           thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
@@ -1822,9 +1803,7 @@ static int binlog_rollback(handlerton *h
     else if (ending_trans(thd, all) ||
              (!(thd->variables.option_bits & OPTION_KEEP_LOG) &&
               (!stmt_has_updated_non_trans_table(thd) ||
-               thd->variables.binlog_format != BINLOG_FORMAT_STMT) &&
-              (!cache_mngr->trx_cache.changes_to_non_trans_temp_table() ||
-               thd->variables.binlog_format != BINLOG_FORMAT_MIXED)))
+               thd->variables.binlog_format != BINLOG_FORMAT_STMT)))
       error= binlog_truncate_trx_cache(thd, cache_mngr, all);
   }
 
@@ -4701,9 +4680,6 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
       file= cache_mngr->get_binlog_cache_log(is_trans_cache);
       cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
 
-      if (thd->lex->stmt_accessed_non_trans_temp_table())
-        cache_data->set_changes_to_non_trans_temp_table();
-
       thd->binlog_start_trans_and_stmt();
     }
     DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-07-09 09:05:17 +0000
+++ b/sql/log_event.cc	2010-07-11 19:35:51 +0000
@@ -678,11 +678,11 @@ Log_event::Log_event(THD* thd_arg, uint1
 {
   server_id=	thd->server_id;
   when=		thd->start_time;
-  cache_type= ((using_trans || stmt_has_updated_trans_table(thd) ||
-               (thd->lex->stmt_accessed_temp_table() &&
-               trans_has_updated_trans_table(thd)))
-               ? Log_event::EVENT_TRANSACTIONAL_CACHE :
-               Log_event::EVENT_STMT_CACHE);
+
+  if (using_trans) 
+    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+  else 
+    cache_type= Log_event::EVENT_STMT_CACHE;
 }
 
 /**
@@ -2468,21 +2468,18 @@ Query_log_event::Query_log_event(THD* th
 
   LEX *lex= thd->lex;
   /*
-    TRUE defines that either a trx-cache or stmt-cache must be used
-    and wrapped by a BEGIN...COMMIT. Otherwise, the statement will
-    be written directly to the binary log without being wrapped by
-    a BEGIN...COMMIT.
+    Defines that the statement will be written directly to the binary log
+    without being wrapped by a BEGIN...COMMIT. Otherwise, the statement
+    will be written to either the trx-cache or stmt-cache.
 
-    Note that a cache will not be used if the parameter direct is
-    TRUE.
+    Note that a cache will not be used if the parameter direct is TRUE.
   */
   bool use_cache= FALSE;
   /*
-    TRUE defines that the trx-cache must be used and by consequence
-    the use_cache is TRUE.
+    TRUE defines that the trx-cache must be used and by consequence the
+    use_cache is TRUE.
 
-    Note that a cache will not be used if the parameter direct is
-    TRUE.
+    Note that a cache will not be used if the parameter direct is TRUE.
   */
   bool trx_cache= FALSE;
   cache_type= Log_event::EVENT_INVALID_CACHE;
@@ -2490,16 +2487,14 @@ Query_log_event::Query_log_event(THD* th
   switch (lex->sql_command)
   {
     case SQLCOM_DROP_TABLE:
-      use_cache= trx_cache= (lex->drop_temporary &&
-                            thd->in_multi_stmt_transaction_mode());
+      use_cache= (lex->drop_temporary && thd->in_multi_stmt_transaction_mode());
     break;
 
     case SQLCOM_CREATE_TABLE:
-      use_cache= trx_cache=
-                 ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
-                   thd->in_multi_stmt_transaction_mode()) ||
-                 (lex->select_lex.item_list.elements &&
+      trx_cache= (lex->select_lex.item_list.elements &&
                   thd->is_current_stmt_binlog_format_row());
+      use_cache= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+                   thd->in_multi_stmt_transaction_mode()) || trx_cache;
       break;
     case SQLCOM_SET_OPTION:
       use_cache= trx_cache= (lex->autocommit ? FALSE : TRUE);
@@ -2518,14 +2513,13 @@ Query_log_event::Query_log_event(THD* th
   {
     cache_type= Log_event::EVENT_NO_CACHE;
   }
-  else
-  {
-    cache_type= ((using_trans || stmt_has_updated_trans_table(thd) || trx_cache ||
-                 (thd->lex->stmt_accessed_temp_table() &&
-                 trans_has_updated_trans_table(thd)))
-                 ? Log_event::EVENT_TRANSACTIONAL_CACHE :
-                 Log_event::EVENT_STMT_CACHE);
-  }
+  else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) || 
+           thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
+                                          thd->tx_isolation,
+                                          trans_has_updated_trans_table(thd)))
+    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+  else 
+    cache_type= Log_event::EVENT_STMT_CACHE;
   DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
   DBUG_PRINT("info",("Query_log_event has flags2: %lu  sql_mode: %lu",
                      (ulong) flags2, sql_mode));

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-07-09 09:05:17 +0000
+++ b/sql/sql_class.cc	2010-07-11 19:35:51 +0000
@@ -3768,124 +3768,14 @@ int THD::decide_logging_format(TABLE_LIS
     int error= 0;
     int unsafe_flags;
 
-    /*
-      Classify a statement as unsafe when there is a mixed statement and an
-      on-going transaction at any point of the execution if:
-
-        1. The mixed statement is about to update a transactional table and
-        a non-transactional table.
-
-        2. The mixed statement is about to update a temporary transactional
-        table and a non-transactional table.
-      
-        3. The mixed statement is about to update a transactional table and
-        read from a non-transactional table.
-
-        4. The mixed statement is about to update a temporary transactional
-        table and read from a non-transactional table.
-
-        5. The mixed statement is about to update a non-transactional table
-        and read from a transactional table when the isolation level is
-        lower than repeatable read.
-
-      After updating a transactional table if:
-
-        6. The mixed statement is about to update a non-transactional table
-        and read from a temporary transactional table.
- 
-        7. The mixed statement is about to update a non-transactional table
-        and read from a temporary transactional table.
-
-        8. The mixed statement is about to update a non-transactionala table
-        and read from a temporary non-transactional table.
-     
-        9. The mixed statement is about to update a temporary non-transactional
-        table and update a non-transactional table.
-     
-        10. The mixed statement is about to update a temporary non-transactional
-        table and read from a non-transactional table.
-     
-        11. A statement is about to update a non-transactional table and the
-        option variables.binlog_direct_non_trans_update is OFF.
-
-      The reason for this is that locks acquired may not protected a concurrent
-      transaction of interfering in the current execution and by consequence in
-      the result. In particular, if there is an on-going transaction and a
-      transactional table was already updated, a temporary table must be written
-      to the binary log in the boundaries of the on-going transaction and as
-      such we artificially classify them as transactional.
-    */
-    if (in_multi_stmt_transaction_mode())
-    {
-      my_bool mixed_unsafe= FALSE;
-      my_bool non_trans_unsafe= FALSE;
-
-      /* Case 1. */
-      if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
-          lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
-        mixed_unsafe= TRUE;
-      /* Case 2. */
-      else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
-               lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
-        mixed_unsafe= TRUE;
-      /* Case 3. */
-      else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
-               lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
-        mixed_unsafe= TRUE;
-      /* Case 4. */
-      else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
-               lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
-        mixed_unsafe= TRUE;
-      /* Case 5. */
-      else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
-               lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE) &&
-               tx_isolation < ISO_REPEATABLE_READ)
-        /*
-           By default, InnoDB operates in REPEATABLE READ and with the option
-           --innodb-locks-unsafe-for-binlog disabled. In this case, InnoDB uses
-           next-key locks for searches and index scans, which prevents phantom
-           rows.
- 
-           This is scenario is safe for Innodb. However, there are no means to
-           transparently get this information. Therefore, we need to improve this
-           and change the storage engines to report somehow when an execution is
-           safe under an isolation level & binary logging format.
-        */
-        mixed_unsafe= TRUE;
-
-      if (trans_has_updated_trans_table(this))
-      {
-        /* Case 6. */
-        if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
-            lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE))
-          mixed_unsafe= TRUE;
-        /* Case 7. */
-        else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
-                 lex->stmt_accessed_table(LEX::STMT_READS_TEMP_TRANS_TABLE))
-          mixed_unsafe= TRUE;
-        /* Case 8. */
-        else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
-                 lex->stmt_accessed_table(LEX::STMT_READS_TEMP_NON_TRANS_TABLE))
-          mixed_unsafe= TRUE;
-        /* Case 9. */
-        else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
-                 lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
-          mixed_unsafe= TRUE;
-        /* Case 10. */
-        else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
-                 lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
-        mixed_unsafe= TRUE;
-        /* Case 11. */
-        else if (!variables.binlog_direct_non_trans_update &&
-                 lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
-          non_trans_unsafe= TRUE;
-      }
-
-      if (mixed_unsafe)
-        lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
-      else if (non_trans_unsafe)
-        lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS);
-    }
+    bool multi_stmt_trans= in_multi_stmt_transaction_mode();
+    bool trans_table= trans_has_updated_trans_table(this);
+    if (lex->is_mixed_stmt_unsafe(multi_stmt_trans, tx_isolation, trans_table))
+      lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
+    else if (multi_stmt_trans && trans_table &&
+             !variables.binlog_direct_non_trans_update &&
+             lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
+      lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS);
 
     /*
       If more than one engine is involved in the statement and at

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-07-09 09:05:17 +0000
+++ b/sql/sql_lex.h	2010-07-11 19:35:51 +0000
@@ -1332,7 +1332,7 @@ public:
   */
   inline void set_stmt_accessed_table(enum_stmt_accessed_table accessed_table)
   {
-    DBUG_ENTER("THD::set_stmt_accessed_table");
+    DBUG_ENTER("LEX::set_stmt_accessed_table");
 
     DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
     stmt_accessed_table_flag |= (1U << accessed_table);
@@ -1353,49 +1353,156 @@ public:
   */
   inline bool stmt_accessed_table(enum_stmt_accessed_table accessed_table)
   {
-    DBUG_ENTER("THD::stmt_accessed_table");
+    DBUG_ENTER("LEX::stmt_accessed_table");
 
     DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
 
     DBUG_RETURN((stmt_accessed_table_flag & (1U << accessed_table)) != 0);
   }
 
-  /**
-    Checks if a temporary table is about to be accessed while executing a
-    statement.
-
-    @return
-      @retval TRUE  if a temporary table is about to be accessed
-      @retval FALSE otherwise
-  */
-  inline bool stmt_accessed_temp_table()
+  inline bool is_mixed_stmt_unsafe(bool in_multi_stmt_transaction_mode,
+                                   uint tx_isolation,
+                                   bool trx_cache_is_not_empty)
   {
-    DBUG_ENTER("THD::stmt_accessed_temp_table");
-
-    DBUG_RETURN((stmt_accessed_table_flag &
-                ((1U << STMT_READS_TEMP_TRANS_TABLE) |
-                 (1U << STMT_WRITES_TEMP_TRANS_TABLE) |
-                 (1U << STMT_READS_TEMP_NON_TRANS_TABLE) |
-                 (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0);
-  }
+    my_bool mixed_unsafe= FALSE;
 
-  /**
-    Checks if a temporary non-transactional table is about to be accessed
-    while executing a statement.
+    DBUG_ENTER("LEX::is_mixed_stmt_unsafe");
+    /*
+      Classify a statement as unsafe when there is a mixed statement and an
+      on-going transaction at any point of the execution if:
 
-    @return
-      @retval TRUE  if a temporary non-transactional table is about to be
-                    accessed
-      @retval FALSE otherwise
-  */
-  inline bool stmt_accessed_non_trans_temp_table()
-  {
-    DBUG_ENTER("THD::stmt_accessed_non_trans_temp_table");
+        1. The mixed statement is about to update a transactional table and
+        a non-transactional table.
 
-    DBUG_RETURN((stmt_accessed_table_flag &
-                ((1U << STMT_READS_TEMP_NON_TRANS_TABLE) |
-                 (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0);
-  }
+        2. The mixed statement is about to update a temporary transactional
+        table and a non-transactional table.
+      
+        3. The mixed statement is about to update a transactional table and
+        read from a non-transactional table.
+
+        4. The mixed statement is about to update a temporary transactional
+        table and read from a non-transactional table.
+
+        5. The mixed statement is about to update a non-transactional table
+        and read from a transactional table when the isolation level is
+        lower than repeatable read.
+
+      After updating a transactional table if:
+
+        6. The mixed statement is about to update a non-transactional table
+        and read from a temporary transactional table.
+ 
+        7. The mixed statement is about to update a non-transactional table
+        and read from a temporary transactional table.
+
+        8. The mixed statement is about to update a non-transactionala table
+        and read from a temporary non-transactional table.
+     
+        9. The mixed statement is about to update a temporary non-transactional
+        table and update a non-transactional table.
+     
+        10. The mixed statement is about to update a temporary non-transactional
+        table and read from a non-transactional table.
+     
+        11. A statement is about to update a non-transactional table and the
+        option variables.binlog_direct_non_trans_update is OFF.
+
+      The reason for this is that locks acquired may not protected a concurrent
+      transaction of interfering in the current execution and by consequence in
+      the result. In particular, if there is an on-going transaction and a
+      transactional table was already updated, a temporary table must be written
+      to the binary log in the boundaries of the on-going transaction and as
+      such we artificially classify them as transactional.
+    */
+    if (in_multi_stmt_transaction_mode)
+    {
+      /* Case 1. */
+      if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+          stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 2. */
+      else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 3. */
+      else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 4. */
+      else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_READS_TEMP_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 5. */
+      else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 6. */
+      else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_READS_TRANS_TABLE) &&
+               tx_isolation < ISO_REPEATABLE_READ)
+        /*
+          By default, InnoDB operates in REPEATABLE READ and with the option
+          --innodb-locks-unsafe-for-binlog disabled. In this case, InnoDB uses
+          next-key locks for searches and index scans, which prevents phantom
+          rows.
+ 
+          This is scenario is safe for Innodb. However, there are no means to
+          transparently get this information. Therefore, we need to improve this
+          and change the storage engines to report somehow when an execution is
+          safe under an isolation level & binary logging format.
+        */
+        mixed_unsafe= TRUE;
+      /* Case 7. */
+      else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 8. */
+      else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+              stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 9. */
+      else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_READS_TEMP_NON_TRANS_TABLE))
+        mixed_unsafe= TRUE;
+      /* Case 10. */
+      else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+               stmt_accessed_table(STMT_READS_TRANS_TABLE) &&
+               tx_isolation < ISO_REPEATABLE_READ)
+        /*
+          By default, InnoDB operates in REPEATABLE READ and with the option
+          --innodb-locks-unsafe-for-binlog disabled. In this case, InnoDB uses
+          next-key locks for searches and index scans, which prevents phantom
+          rows.
+
+          This is scenario is safe for Innodb. However, there are no means to
+          transparently get this information. Therefore, we need to improve this
+          and change the storage engines to report somehow when an execution is
+          safe under an isolation level & binary logging format.
+        */
+        mixed_unsafe= TRUE;
+
+      if (trx_cache_is_not_empty)
+      {
+        /* Case 11. */
+        if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+            stmt_accessed_table(STMT_READS_TRANS_TABLE))
+          mixed_unsafe= TRUE;
+        /* Case 12 */
+        else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+                 stmt_accessed_table(STMT_READS_TEMP_TRANS_TABLE))
+          mixed_unsafe= TRUE;
+        /* Case 13. */
+        else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+                 stmt_accessed_table(STMT_READS_TRANS_TABLE))
+          mixed_unsafe= TRUE;
+        /* Case 14. */
+        else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+                 stmt_accessed_table(STMT_READS_TEMP_TRANS_TABLE))
+          mixed_unsafe= TRUE;
+      }
+    } 
+    DBUG_RETURN(mixed_unsafe);
+  }  
 
   /**
     true if the parsed tree contains references to stored procedures


Attachment: [text/bzr-bundle]
Thread
bzr commit into mysql-trunk-bugfixing branch (alfranio.correia:3087)Alfranio Correia11 Jul