Loading mysql-test/r/ndb_lock.result +11 −0 Original line number Diff line number Diff line Loading @@ -63,3 +63,14 @@ pk u o 5 5 5 insert into t1 values (1,1,1); drop table t1; create table t3 (id2 int) engine=ndb; lock tables t3 write; unlock tables; drop table t3; create table t2 (id int, j int) engine=ndb; insert into t2 values (2, 2); create table t3 (id int) engine=ndb; lock tables t3 read; delete t2 from t2, t3 where t2.id = t3.id; unlock tables; drop table t2, t3; mysql-test/t/ndb_lock.test +36 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,39 @@ insert into t1 values (1,1,1); drop table t1; # End of 4.1 tests # # Bug #17812 Previous lock table for write causes "stray" lock # although table is recreated # # this creating, locking, and dropping causes a subsequent hang # on the delete below waiting for table t2 the locking in the # "other" connection is relevant, as without it there is no problem # connection con1; create table t3 (id2 int) engine=ndb; connection con2; lock tables t3 write; unlock tables; connection con1; drop table t3; connection con1; create table t2 (id int, j int) engine=ndb; insert into t2 values (2, 2); create table t3 (id int) engine=ndb; connection con2; lock tables t3 read; connection con1; # here we get a hang before bugfix although we shouldn't delete t2 from t2, t3 where t2.id = t3.id; connection con2; unlock tables; connection con1; drop table t2, t3; sql/ha_ndbcluster.cc +32 −33 Original line number Diff line number Diff line Loading @@ -466,60 +466,58 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) # The mapped error code */ int ha_ndbcluster::invalidate_dictionary_cache(TABLE_SHARE *share, Ndb *ndb, const char *dbname, const char *tabname, bool global) int ha_ndbcluster::invalidate_dictionary_cache(bool global) { NDBDICT *dict= ndb->getDictionary(); NDBDICT *dict= get_ndb()->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); DBUG_PRINT("info", ("invalidating %s", tabname)); DBUG_PRINT("info", ("m_tabname: %s global: %d", m_tabname, global)); if (global) { #ifdef HAVE_NDB_BINLOG if (current_thd != injector_thd) { char key[FN_REFLEN]; build_table_filename(key, sizeof(key), dbname, tabname, ""); build_table_filename(key, sizeof(key), m_dbname, m_tabname, ""); DBUG_PRINT("info", ("Getting ndbcluster mutex")); pthread_mutex_lock(&ndbcluster_mutex); NDB_SHARE *ndb_share= (NDB_SHARE*)hash_search(&ndbcluster_open_tables, (byte*) key, strlen(key)); // Only binlog_thread is allowed to globally invalidate a table if (ndb_share && ndb_share->op) { pthread_mutex_unlock(&ndbcluster_mutex); DBUG_PRINT("info", ("Released ndbcluster mutex")); // Only binlog_thread is allowed to globally invalidate a table if (global && ndb_share && ndb_share->op && (current_thd != injector_thd)) DBUG_RETURN(1); } pthread_mutex_unlock(&ndbcluster_mutex); DBUG_PRINT("info", ("Released ndbcluster mutex")); } #endif if (global) { const NDBTAB *tab= dict->getTable(tabname); const NDBTAB *tab= dict->getTable(m_tabname); if (!tab) DBUG_RETURN(1); if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { // Global cache has already been invalidated dict->removeCachedTable(tabname); dict->removeCachedTable(m_tabname); global= FALSE; DBUG_PRINT("info", ("global: %d", global)); } else dict->invalidateTable(tabname); dict->invalidateTable(m_tabname); table_share->version= 0L; /* Free when thread is ready */ } else dict->removeCachedTable(tabname); share->version=0L; /* Free when thread is ready */ DBUG_RETURN(0); } dict->removeCachedTable(m_tabname); void ha_ndbcluster::invalidate_dictionary_cache(bool global) { NDBDICT *dict= get_ndb()->getDictionary(); if (invalidate_dictionary_cache(table_share, get_ndb(), m_dbname, m_tabname, global)) return; /* Invalidate indexes */ for (uint i= 0; i < table_share->keys; i++) { NDBINDEX *index = (NDBINDEX *) m_index[i].index; NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index; if (!index && !unique_index) continue; if (!index && !unique_index) continue; NDB_INDEX_TYPE idx_type= m_index[i].type; switch (idx_type) { Loading @@ -546,6 +544,7 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) break; } } DBUG_RETURN(0); } int ha_ndbcluster::ndb_err(NdbTransaction *trans) Loading sql/ha_ndbcluster.h +1 −4 Original line number Diff line number Diff line Loading @@ -685,9 +685,6 @@ static void set_tabname(const char *pathname, char *tabname); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); static int invalidate_dictionary_cache(TABLE_SHARE *share, Ndb *ndb, const char *dbname, const char *tabname, bool global); private: friend int ndbcluster_drop_database_impl(const char *path); Loading Loading @@ -774,7 +771,7 @@ static void set_tabname(const char *pathname, char *tabname); void print_results(); ulonglong get_auto_increment(); void invalidate_dictionary_cache(bool global); int invalidate_dictionary_cache(bool global); int ndb_err(NdbTransaction*); bool uses_blob_value(); Loading storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -1252,12 +1252,14 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep) * Already completed GCI... * Possible in case of resend during NF handling */ #ifdef VM_TRACE ndbout << "bucket == 0, gci:" << gci << " complete: " << m_complete_data << endl; for(Uint32 i = 0; i<m_active_gci.size(); i++) { ndbout << i << " - " << m_active_gci[i] << endl; } #endif DBUG_VOID_RETURN_EVENT; } Loading Loading
mysql-test/r/ndb_lock.result +11 −0 Original line number Diff line number Diff line Loading @@ -63,3 +63,14 @@ pk u o 5 5 5 insert into t1 values (1,1,1); drop table t1; create table t3 (id2 int) engine=ndb; lock tables t3 write; unlock tables; drop table t3; create table t2 (id int, j int) engine=ndb; insert into t2 values (2, 2); create table t3 (id int) engine=ndb; lock tables t3 read; delete t2 from t2, t3 where t2.id = t3.id; unlock tables; drop table t2, t3;
mysql-test/t/ndb_lock.test +36 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,39 @@ insert into t1 values (1,1,1); drop table t1; # End of 4.1 tests # # Bug #17812 Previous lock table for write causes "stray" lock # although table is recreated # # this creating, locking, and dropping causes a subsequent hang # on the delete below waiting for table t2 the locking in the # "other" connection is relevant, as without it there is no problem # connection con1; create table t3 (id2 int) engine=ndb; connection con2; lock tables t3 write; unlock tables; connection con1; drop table t3; connection con1; create table t2 (id int, j int) engine=ndb; insert into t2 values (2, 2); create table t3 (id int) engine=ndb; connection con2; lock tables t3 read; connection con1; # here we get a hang before bugfix although we shouldn't delete t2 from t2, t3 where t2.id = t3.id; connection con2; unlock tables; connection con1; drop table t2, t3;
sql/ha_ndbcluster.cc +32 −33 Original line number Diff line number Diff line Loading @@ -466,60 +466,58 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) # The mapped error code */ int ha_ndbcluster::invalidate_dictionary_cache(TABLE_SHARE *share, Ndb *ndb, const char *dbname, const char *tabname, bool global) int ha_ndbcluster::invalidate_dictionary_cache(bool global) { NDBDICT *dict= ndb->getDictionary(); NDBDICT *dict= get_ndb()->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); DBUG_PRINT("info", ("invalidating %s", tabname)); DBUG_PRINT("info", ("m_tabname: %s global: %d", m_tabname, global)); if (global) { #ifdef HAVE_NDB_BINLOG if (current_thd != injector_thd) { char key[FN_REFLEN]; build_table_filename(key, sizeof(key), dbname, tabname, ""); build_table_filename(key, sizeof(key), m_dbname, m_tabname, ""); DBUG_PRINT("info", ("Getting ndbcluster mutex")); pthread_mutex_lock(&ndbcluster_mutex); NDB_SHARE *ndb_share= (NDB_SHARE*)hash_search(&ndbcluster_open_tables, (byte*) key, strlen(key)); // Only binlog_thread is allowed to globally invalidate a table if (ndb_share && ndb_share->op) { pthread_mutex_unlock(&ndbcluster_mutex); DBUG_PRINT("info", ("Released ndbcluster mutex")); // Only binlog_thread is allowed to globally invalidate a table if (global && ndb_share && ndb_share->op && (current_thd != injector_thd)) DBUG_RETURN(1); } pthread_mutex_unlock(&ndbcluster_mutex); DBUG_PRINT("info", ("Released ndbcluster mutex")); } #endif if (global) { const NDBTAB *tab= dict->getTable(tabname); const NDBTAB *tab= dict->getTable(m_tabname); if (!tab) DBUG_RETURN(1); if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { // Global cache has already been invalidated dict->removeCachedTable(tabname); dict->removeCachedTable(m_tabname); global= FALSE; DBUG_PRINT("info", ("global: %d", global)); } else dict->invalidateTable(tabname); dict->invalidateTable(m_tabname); table_share->version= 0L; /* Free when thread is ready */ } else dict->removeCachedTable(tabname); share->version=0L; /* Free when thread is ready */ DBUG_RETURN(0); } dict->removeCachedTable(m_tabname); void ha_ndbcluster::invalidate_dictionary_cache(bool global) { NDBDICT *dict= get_ndb()->getDictionary(); if (invalidate_dictionary_cache(table_share, get_ndb(), m_dbname, m_tabname, global)) return; /* Invalidate indexes */ for (uint i= 0; i < table_share->keys; i++) { NDBINDEX *index = (NDBINDEX *) m_index[i].index; NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index; if (!index && !unique_index) continue; if (!index && !unique_index) continue; NDB_INDEX_TYPE idx_type= m_index[i].type; switch (idx_type) { Loading @@ -546,6 +544,7 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) break; } } DBUG_RETURN(0); } int ha_ndbcluster::ndb_err(NdbTransaction *trans) Loading
sql/ha_ndbcluster.h +1 −4 Original line number Diff line number Diff line Loading @@ -685,9 +685,6 @@ static void set_tabname(const char *pathname, char *tabname); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); static int invalidate_dictionary_cache(TABLE_SHARE *share, Ndb *ndb, const char *dbname, const char *tabname, bool global); private: friend int ndbcluster_drop_database_impl(const char *path); Loading Loading @@ -774,7 +771,7 @@ static void set_tabname(const char *pathname, char *tabname); void print_results(); ulonglong get_auto_increment(); void invalidate_dictionary_cache(bool global); int invalidate_dictionary_cache(bool global); int ndb_err(NdbTransaction*); bool uses_blob_value(); Loading
storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -1252,12 +1252,14 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep) * Already completed GCI... * Possible in case of resend during NF handling */ #ifdef VM_TRACE ndbout << "bucket == 0, gci:" << gci << " complete: " << m_complete_data << endl; for(Uint32 i = 0; i<m_active_gci.size(); i++) { ndbout << i << " - " << m_active_gci[i] << endl; } #endif DBUG_VOID_RETURN_EVENT; } Loading