MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:tomas Date:April 19 2006 12:54pm
Subject:bk commit into 5.1 tree (tomas:1.2372) BUG#18094
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2372 06/04/19 14:54:39 tomas@stripped +8 -0
  BUG#18094 Slave caches invalid table definition after atlters causes select failure
  - return correct object status from ndb dictionary
  - check for validity of index retrieved from index, and retry if invalid

  storage/ndb/src/ndbapi/NdbDictionary.cpp
    1.55 06/04/19 14:54:32 tomas@stripped +33 -3
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  storage/ndb/include/ndbapi/NdbDictionary.hpp
    1.73 06/04/19 14:54:32 tomas@stripped +4 -0
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  sql/ha_ndbcluster_binlog.cc
    1.45 06/04/19 14:54:32 tomas@stripped +15 -7
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  sql/ha_ndbcluster.h
    1.131 06/04/19 14:54:32 tomas@stripped +3 -2
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  sql/ha_ndbcluster.cc
    1.298 06/04/19 14:54:32 tomas@stripped +58 -26
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  mysql-test/t/rpl_ndb_basic.test
    1.5 06/04/19 14:54:32 tomas@stripped +31 -0
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  mysql-test/t/disabled.def
    1.134 06/04/19 14:54:32 tomas@stripped +2 -2
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

  mysql-test/r/rpl_ndb_basic.result
    1.3 06/04/19 14:54:31 tomas@stripped +25 -0
    BUG#18094 Slave caches invalid table definition after atlters causes select failure
    - return correct object status from ndb dictionary
    - check for validity of index retrieved from index, and retry if invalid

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	tomas
# Host:	poseidon.ndb.mysql.com
# Root:	/home/tomas/mysql-5.1-new

--- 1.133/mysql-test/t/disabled.def	2006-04-13 22:25:54 +02:00
+++ 1.134/mysql-test/t/disabled.def	2006-04-19 14:54:32 +02:00
@@ -25,9 +25,9 @@
 rpl_ndb_2myisam          : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs
 rpl_ndb_auto_inc         : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er
 rpl_ndb_ddl              : result file needs update + test needs to checked
-rpl_ndb_innodb2ndb       : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure
+rpl_ndb_innodb2ndb       : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave.
 rpl_ndb_log              : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ
-rpl_ndb_myisam2ndb       : BUG#18094 2006-03-16 mats   Slave caches invalid table definition after atlters causes select failure
+rpl_ndb_myisam2ndb       : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave.
 rpl_ndb_relay_space      : BUG#16993 2006-02-16 jmiller RBR: ALTER TABLE ZEROFILL AUTO_INCREMENT is not replicated correctly
 rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian
 rpl_row_basic_7ndb       : BUG#17400 2006-04-09 brian   Cluster Replication: delete & update of rows in table without pk fails on slave.

--- 1.72/storage/ndb/include/ndbapi/NdbDictionary.hpp	2006-03-23 04:17:22 +01:00
+++ 1.73/storage/ndb/include/ndbapi/NdbDictionary.hpp	2006-04-19 14:54:32 +02:00
@@ -1745,11 +1745,15 @@
 		  const char * tableName);
     
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    void removeCachedTable(const Table *table);
+    void removeCachedIndex(const Index *index);
+    void invalidateTable(const Table *table);
     /**
      * Invalidate cached index object
      */
     void invalidateIndex(const char * indexName,
                          const char * tableName);
+    void invalidateIndex(const Index *index);
     /**
      * Force gcp and wait for gcp complete
      */

--- 1.54/storage/ndb/src/ndbapi/NdbDictionary.cpp	2006-03-06 11:13:55 +01:00
+++ 1.55/storage/ndb/src/ndbapi/NdbDictionary.cpp	2006-04-19 14:54:32 +02:00
@@ -772,17 +772,17 @@
 
 NdbDictionary::Object::Status
 NdbDictionary::Index::getObjectStatus() const {
-  return m_impl.m_status;
+  return m_impl.m_table->m_status;
 }
 
 int 
 NdbDictionary::Index::getObjectVersion() const {
-  return m_impl.m_version;
+  return m_impl.m_table->m_version;
 }
 
 int 
 NdbDictionary::Index::getObjectId() const {
-  return m_impl.m_id;
+  return m_impl.m_table->m_id;
 }
 
 
@@ -1396,12 +1396,24 @@
 }
 
 void
+NdbDictionary::Dictionary::invalidateTable(const Table *table){
+  NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+  m_impl.invalidateObject(t);
+}
+
+void
 NdbDictionary::Dictionary::removeCachedTable(const char * name){
   NdbTableImpl * t = m_impl.getTable(name);
   if(t)
     m_impl.removeCachedObject(* t);
 }
 
+void
+NdbDictionary::Dictionary::removeCachedTable(const Table *table){
+  NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+  m_impl.removeCachedObject(t);
+}
+
 int
 NdbDictionary::Dictionary::createIndex(const Index & ind)
 {
@@ -1426,6 +1438,15 @@
 }
 
 void
+NdbDictionary::Dictionary::invalidateIndex(const Index *index){
+  DBUG_ENTER("NdbDictionary::Dictionary::invalidateIndex");
+  NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+  assert(i.m_table != 0);
+  m_impl.invalidateObject(* i.m_table);
+  DBUG_VOID_RETURN;
+}
+
+void
 NdbDictionary::Dictionary::invalidateIndex(const char * indexName,
                                            const char * tableName){
   DBUG_ENTER("NdbDictionaryImpl::invalidateIndex");
@@ -1441,6 +1462,15 @@
 NdbDictionary::Dictionary::forceGCPWait()
 {
   return m_impl.forceGCPWait();
+}
+
+void
+NdbDictionary::Dictionary::removeCachedIndex(const Index *index){
+  DBUG_ENTER("NdbDictionary::Dictionary::removeCachedIndex");
+  NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+  assert(i.m_table != 0);
+  m_impl.removeCachedObject(* i.m_table);
+  DBUG_VOID_RETURN;
 }
 
 void

--- 1.297/sql/ha_ndbcluster.cc	2006-04-18 08:59:51 +02:00
+++ 1.298/sql/ha_ndbcluster.cc	2006-04-19 14:54:32 +02:00
@@ -466,7 +466,7 @@
     #   The mapped error code
 */
 
-int ha_ndbcluster::invalidate_dictionary_cache(bool global)
+int ha_ndbcluster::invalidate_dictionary_cache(bool global, const NDBTAB *ndbtab)
 {
   NDBDICT *dict= get_ndb()->getDictionary();
   DBUG_ENTER("invalidate_dictionary_cache");
@@ -494,20 +494,17 @@
       DBUG_PRINT("info", ("Released ndbcluster mutex"));
     }
 #endif
-    const NDBTAB *tab= dict->getTable(m_tabname);
-    if (!tab)
-      DBUG_RETURN(1);
-    if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+    if (!ndbtab)
     {
-      // Global cache has already been invalidated
-      dict->removeCachedTable(m_tabname);
-      global= FALSE;
-      DBUG_PRINT("info", ("global: %d", global));
+      ndbtab= dict->getTable(m_tabname);
+      if (!ndbtab)
+        DBUG_RETURN(1);
     }
-    else
-      dict->invalidateTable(m_tabname);
+    dict->invalidateTable(ndbtab);
     table_share->version= 0L;			/* Free when thread is ready */
   }
+  else if (ndbtab)
+    dict->removeCachedTable(ndbtab);
   else
     dict->removeCachedTable(m_tabname);
 
@@ -564,7 +561,7 @@
     table_list.alias= table_list.table_name= m_tabname;
     close_cached_tables(current_thd, 0, &table_list);
 
-    invalidate_dictionary_cache(TRUE);
+    invalidate_dictionary_cache(TRUE, m_table);
 
     if (err.code==284)
     {
@@ -1041,7 +1038,7 @@
     // Check if thread has stale local cache
     if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
     {
-      invalidate_dictionary_cache(FALSE);
+      invalidate_dictionary_cache(FALSE, tab);
       if (!(tab= dict->getTable(m_tabname)))
          ERR_RETURN(dict->getNdbError());
       DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
@@ -1064,7 +1061,7 @@
       if (!invalidating_ndb_table)
       {
         DBUG_PRINT("info", ("Invalidating table"));
-        invalidate_dictionary_cache(TRUE);
+        invalidate_dictionary_cache(TRUE, tab);
         invalidating_ndb_table= TRUE;
       }
       else
@@ -1091,7 +1088,7 @@
     DBUG_RETURN(error);
   
   m_table_version= tab->getObjectVersion();
-  m_table= (void *)tab; 
+  m_table= tab; 
   m_table_info= NULL; // Set in external lock
   
   DBUG_RETURN(open_indexes(ndb, table, FALSE));
@@ -1150,7 +1147,7 @@
   // Check if thread has stale local cache
   if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
   {
-    dict->removeCachedTable(m_tabname);
+    dict->removeCachedTable(orig_tab);
     if (!(orig_tab= dict->getTable(m_tabname)))
       ERR_RETURN(dict->getNdbError());
   }
@@ -1219,13 +1216,31 @@
   int error= 0;
   NDB_INDEX_TYPE idx_type= get_index_type_from_table(index_no);
   m_index[index_no].type= idx_type;
-  DBUG_ENTER("ha_ndbcluster::get_index_handle");
+  DBUG_ENTER("ha_ndbcluster::add_index_handle");
+  DBUG_PRINT("enter", ("table %s", m_tabname));
 
   if (idx_type != PRIMARY_KEY_INDEX && idx_type != UNIQUE_INDEX)
   {
     DBUG_PRINT("info", ("Get handle to index %s", index_name));
-    const NDBINDEX *index= dict->getIndex(index_name, m_tabname);
-    if (!index) ERR_RETURN(dict->getNdbError());
+    const NDBINDEX *index;
+    do
+    {
+      index= dict->getIndex(index_name, m_tabname);
+      if (!index)
+        ERR_RETURN(dict->getNdbError());
+      DBUG_PRINT("info", ("index: 0x%x  id: %d  version: %d.%d  status: %d",
+                          index,
+                          index->getObjectId(),
+                          index->getObjectVersion() & 0xFFFFFF,
+                          index->getObjectVersion() >> 24,
+                          index->getObjectStatus()));
+      if (index->getObjectStatus() != NdbDictionary::Object::Retrieved)
+      {
+        dict->removeCachedIndex(index);
+        continue;
+      }
+      break;
+    } while (1);
     m_index[index_no].index= (void *) index;
     // ordered index - add stats
     NDB_INDEX_DATA& d=m_index[index_no];
@@ -1254,8 +1269,25 @@
     m_has_unique_index= TRUE;
     strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
     DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name));
-    const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname);
-    if (!index) ERR_RETURN(dict->getNdbError());
+    const NDBINDEX *index;
+    do
+    {
+      index= dict->getIndex(unique_index_name, m_tabname);
+      if (!index)
+        ERR_RETURN(dict->getNdbError());
+      DBUG_PRINT("info", ("index: 0x%x  id: %d  version: %d.%d  status: %d",
+                          index,
+                          index->getObjectId(),
+                          index->getObjectVersion() & 0xFFFFFF,
+                          index->getObjectVersion() >> 24,
+                          index->getObjectStatus()));
+      if (index->getObjectStatus() != NdbDictionary::Object::Retrieved)
+      {
+        dict->removeCachedIndex(index);
+        continue;
+      }
+      break;
+    } while (1);
     m_index[index_no].unique_index= (void *) index;
     error= fix_unique_index_attr_order(m_index[index_no], index, key_info);
   }
@@ -3954,7 +3986,7 @@
       if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved)
 	  || tab->getObjectStatus() == NdbDictionary::Object::Invalid)
       {
-        invalidate_dictionary_cache(FALSE);
+        invalidate_dictionary_cache(FALSE, tab);
         if (!(tab= dict->getTable(m_tabname, &tab_info)))
           ERR_RETURN(dict->getNdbError());
         DBUG_PRINT("info", ("Table schema version: %d", 
@@ -3970,7 +4002,7 @@
       }
       if (m_table != (void *)tab)
       {
-        m_table= (void *)tab;
+        m_table= tab;
         m_table_version = tab->getObjectVersion();
         if (!(my_errno= open_indexes(ndb, table, FALSE)))
           DBUG_RETURN(my_errno);
@@ -4990,7 +5022,7 @@
   // Check if thread has stale local cache
   if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
   {
-    dict->removeCachedTable(m_tabname);
+    dict->removeCachedTable(orig_tab);
     if (!(orig_tab= dict->getTable(m_tabname)))
       ERR_RETURN(dict->getNdbError());
   }
@@ -5002,7 +5034,7 @@
     DBUG_ASSERT(r == 0);
   }
 #endif
-  m_table= (void *)orig_tab;
+  m_table= orig_tab;
   // Change current database to that of target table
   set_dbname(to);
   ndb->setDatabaseName(m_dbname);
@@ -9988,7 +10020,7 @@
     // Check if thread has stale local cache
     if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
     {
-      invalidate_dictionary_cache(FALSE);
+      invalidate_dictionary_cache(FALSE, tab);
       if (!(tab= dict->getTable(m_tabname)))
          ERR_BREAK(dict->getNdbError(), err);
     }

--- 1.130/sql/ha_ndbcluster.h	2006-04-11 14:06:15 +02:00
+++ 1.131/sql/ha_ndbcluster.h	2006-04-19 14:54:32 +02:00
@@ -778,7 +778,8 @@
   void print_results();
 
   ulonglong get_auto_increment();
-  int invalidate_dictionary_cache(bool global);
+  int invalidate_dictionary_cache(bool global,
+                                  const NdbDictionary::Table *ndbtab);
   int ndb_err(NdbTransaction*);
   bool uses_blob_value();
 
@@ -816,7 +817,7 @@
 
   NdbTransaction *m_active_trans;
   NdbScanOperation *m_active_cursor;
-  void *m_table;
+  const NdbDictionary::Table *m_table;
   int m_table_version;
   void *m_table_info;
   char m_dbname[FN_HEADLEN];

--- 1.2/mysql-test/r/rpl_ndb_basic.result	2006-03-07 13:29:48 +01:00
+++ 1.3/mysql-test/r/rpl_ndb_basic.result	2006-04-19 14:54:31 +02:00
@@ -122,3 +122,28 @@
 nid	nom	prenom
 1	DEAD	ABC1
 DROP TABLE t1;
+CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+ALTER TABLE t1 ADD c2 INT;
+SELECT * FROM t1 ORDER BY c1;
+c1	c2
+1	NULL
+2	NULL
+3	NULL
+4	NULL
+5	NULL
+6	NULL
+7	NULL
+8	NULL
+9	NULL
+10	NULL
+ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8;
+ALTER TABLE t1 CHANGE c2 c2 BLOB;
+SELECT * FROM t1 ORDER BY c1 LIMIT 5;
+c1	c2
+1	NULL
+2	NULL
+3	NULL
+4	NULL
+5	NULL
+DROP TABLE t1;

--- 1.4/mysql-test/t/rpl_ndb_basic.test	2006-04-12 15:55:32 +02:00
+++ 1.5/mysql-test/t/rpl_ndb_basic.test	2006-04-19 14:54:32 +02:00
@@ -146,4 +146,35 @@
 # cleanup
 --connection master
 DROP TABLE t1;
+
+
+#
+# BUG#18094
+# Slave caches invalid table definition after atlters causes select failure
+#
+--connection master
+CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB;
+
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+ALTER TABLE t1 ADD c2 INT;
+
+--sync_slave_with_master
+connection slave;
+SELECT * FROM t1 ORDER BY c1;
+
+connection master;
+ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8;
+ALTER TABLE t1 CHANGE c2 c2 BLOB;
+
+--sync_slave_with_master
+connection slave;
+# here we would get error 1412 prior to bug
+SELECT * FROM t1 ORDER BY c1 LIMIT 5;
+
+
+
+# cleanup
+--connection master
+DROP TABLE t1;
 -- source include/master-slave-end.inc

--- 1.44/sql/ha_ndbcluster_binlog.cc	2006-04-18 08:59:52 +02:00
+++ 1.45/sql/ha_ndbcluster_binlog.cc	2006-04-19 14:54:32 +02:00
@@ -1068,20 +1068,27 @@
   MY_BITMAP schema_subscribers;
   uint32 bitbuf[sizeof(ndb_schema_object->slock)/4];
   {
-    int i;
+    int i, updated= 0;
+    int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes();
     bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false);
     bitmap_set_all(&schema_subscribers);
     (void) pthread_mutex_lock(&schema_share->mutex);
-    for (i= 0; i < ndb_number_of_storage_nodes; i++)
+    for (i= 0; i < no_storage_nodes; i++)
     {
       MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i];
       if (!bitmap_is_clear_all(table_subscribers))
+      {
         bitmap_intersect(&schema_subscribers,
                          table_subscribers);
+        updated= 1;
+      }
     }
     (void) pthread_mutex_unlock(&schema_share->mutex);
-    bitmap_clear_bit(&schema_subscribers, node_id);
-      
+    if (updated)
+      bitmap_clear_bit(&schema_subscribers, node_id);
+    else
+      bitmap_clear_all(&schema_subscribers);
+
     if (ndb_schema_object)
     {
       (void) pthread_mutex_lock(&ndb_schema_object->mutex);
@@ -1227,13 +1234,14 @@
     {
       struct timespec abstime;
       int i;
+      int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes();
       set_timespec(abstime, 1);
       int ret= pthread_cond_timedwait(&injector_cond,
                                       &ndb_schema_object->mutex,
                                       &abstime);
 
       (void) pthread_mutex_lock(&schema_share->mutex);
-      for (i= 0; i < ndb_number_of_storage_nodes; i++)
+      for (i= 0; i < no_storage_nodes; i++)
       {
         /* remove any unsubscribed from schema_subscribers */
         MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i];
@@ -1466,7 +1474,7 @@
   (void)strxmov(table_handler.m_dbname, dbname, NullS);
   (void)strxmov(table_handler.m_tabname, tabname, NullS);
   table_handler.open_indexes(ndb, table, TRUE);
-  table_handler.invalidate_dictionary_cache(TRUE);
+  table_handler.invalidate_dictionary_cache(TRUE, 0);
   thd_ndb->ndb= old_ndb;
   
   /*
@@ -1555,7 +1563,7 @@
     table_handler.set_dbname(share->key);
     table_handler.set_tabname(share->key);
     table_handler.open_indexes(ndb, table, TRUE);
-    table_handler.invalidate_dictionary_cache(TRUE);
+    table_handler.invalidate_dictionary_cache(TRUE, 0);
     thd_ndb->ndb= old_ndb;
   }
   DBUG_ASSERT(share->op == pOp || share->op_old == pOp);
Thread
bk commit into 5.1 tree (tomas:1.2372) BUG#18094tomas21 Apr