diff options
-rw-r--r-- | sql/ha_ndbcluster.cc | 63 | ||||
-rw-r--r-- | sql/ha_ndbcluster.h | 2 | ||||
-rw-r--r-- | sql/ha_ndbcluster_binlog.cc | 51 |
3 files changed, 94 insertions, 22 deletions
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 29063a7212f..fe0c7118056 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -121,14 +121,14 @@ static uint ndbcluster_alter_table_flags(uint flags) #define ERR_RETURN(err) \ { \ const NdbError& tmp= err; \ - ERR_PRINT(tmp); \ + set_ndb_err(current_thd, tmp); \ DBUG_RETURN(ndb_to_mysql_error(&tmp)); \ } #define ERR_BREAK(err, code) \ { \ const NdbError& tmp= err; \ - ERR_PRINT(tmp); \ + set_ndb_err(current_thd, tmp); \ code= ndb_to_mysql_error(&tmp); \ break; \ } @@ -516,13 +516,51 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) DBUG_VOID_RETURN; } +/* + Sets the latest ndb error code on the thd_ndb object such that it + can be retrieved later to know which ndb error caused the handler + error. +*/ +static void set_ndb_err(THD *thd, const NdbError &err) +{ + DBUG_ENTER("set_ndb_err"); + ERR_PRINT(err); + + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb == NULL) + DBUG_VOID_RETURN; +#ifdef NOT_YET + /* + Check if error code is overwritten, in this case the original + failure cause will be lost. E.g. if 4350 error is given. So + push a warning so that it can be detected which is the root + error cause. + */ + if (thd_ndb->m_query_id == thd->query_id && + thd_ndb->m_error_code != 0 && + thd_ndb->m_error_code != err.code) + { + char buf[FN_REFLEN]; + ndb_error_string(thd_ndb->m_error_code, buf, sizeof(buf)); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_GET_ERRMSG, ER(ER_GET_ERRMSG), + thd_ndb->m_error_code, buf, "NDB"); + } +#endif + thd_ndb->m_query_id= thd->query_id; + thd_ndb->m_error_code= err.code; + DBUG_VOID_RETURN; +} + int ha_ndbcluster::ndb_err(NdbTransaction *trans) { + THD *thd= current_thd; int res; NdbError err= trans->getNdbError(); DBUG_ENTER("ndb_err"); - ERR_PRINT(err); + set_ndb_err(thd, err); + switch (err.classification) { case NdbError::SchemaError: { @@ -533,7 +571,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) bzero((char*) &table_list,sizeof(table_list)); table_list.db= m_dbname; table_list.alias= table_list.table_name= m_tabname; - close_cached_tables(current_thd, 0, &table_list); + close_cached_tables(thd, 0, &table_list); break; } default: @@ -4576,7 +4614,7 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) { const NdbError err= trans->getNdbError(); const NdbOperation *error_op= trans->getNdbErrorOperation(); - ERR_PRINT(err); + set_ndb_err(thd, err); res= ndb_to_mysql_error(&err); if (res != -1) ndbcluster_print_error(res, error_op); @@ -4627,7 +4665,7 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) { const NdbError err= trans->getNdbError(); const NdbOperation *error_op= trans->getNdbErrorOperation(); - ERR_PRINT(err); + set_ndb_err(thd, err); res= ndb_to_mysql_error(&err); if (res != -1) ndbcluster_print_error(res, error_op); @@ -5212,7 +5250,7 @@ int ha_ndbcluster::create(const char *name, if (dict->createTable(tab) != 0) { const NdbError err= dict->getNdbError(); - ERR_PRINT(err); + set_ndb_err(thd, err); my_errno= ndb_to_mysql_error(&err); DBUG_RETURN(my_errno); } @@ -5226,7 +5264,7 @@ int ha_ndbcluster::create(const char *name, { /* purecov: begin deadcode */ const NdbError err= dict->getNdbError(); - ERR_PRINT(err); + set_ndb_err(thd, err); my_errno= ndb_to_mysql_error(&err); DBUG_RETURN(my_errno); /* purecov: end */ @@ -5398,6 +5436,7 @@ int ha_ndbcluster::create_handler_files(const char *file, new_tab.setFrm(pack_data, pack_length); if (dict->alterTableGlobal(*tab, new_tab)) { + set_ndb_err(current_thd, dict->getNdbError()); error= ndb_to_mysql_error(&dict->getNdbError()); } my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); @@ -5873,6 +5912,7 @@ retry_temporary_error1: default: break; } + set_ndb_err(thd, dict->getNdbError()); res= ndb_to_mysql_error(&dict->getNdbError()); DBUG_PRINT("info", ("error(1) %u", res)); } @@ -5912,6 +5952,7 @@ retry_temporary_error1: } } } + set_ndb_err(thd, dict->getNdbError()); res= ndb_to_mysql_error(&dict->getNdbError()); DBUG_PRINT("info", ("error(2) %u", res)); break; @@ -6271,6 +6312,7 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked) Ndb *ndb= get_ndb(); if (ndb->setDatabaseName(m_dbname)) { + set_ndb_err(current_thd, ndb->getNdbError()); res= ndb_to_mysql_error(&ndb->getNdbError()); break; } @@ -6631,7 +6673,7 @@ int ndbcluster_drop_database_impl(const char *path) const NdbError err= dict->getNdbError(); if (err.code != 709 && err.code != 723) { - ERR_PRINT(err); + set_ndb_err(thd, err); ret= ndb_to_mysql_error(&err); } } @@ -8352,6 +8394,7 @@ retry: my_sleep(retry_sleep); continue; } + set_ndb_err(current_thd, error); break; } while(1); DBUG_PRINT("exit", ("failed, reterr: %u, NdbError %u(%s)", reterr, @@ -9992,7 +10035,7 @@ int ndbcluster_alter_tablespace(handlerton *hton, ndberror: err= dict->getNdbError(); ndberror2: - ERR_PRINT(err); + set_ndb_err(thd, err); ndb_to_mysql_error(&err); my_error(error, MYF(0), errmsg); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index a84ec66f399..5c6646f68af 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -207,6 +207,8 @@ class Thd_ndb NdbTransaction *stmt; bool m_error; bool m_slow_path; + int m_error_code; + uint32 m_query_id; /* query id whn m_error_code was set */ uint32 options; uint32 trans_options; List<NDB_SHARE> changed_tables; diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 391051d8775..3e0e698b2f3 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -81,6 +81,20 @@ static Ndb *injector_ndb= 0; static Ndb *schema_ndb= 0; static int ndbcluster_binlog_inited= 0; +/* + Flag "ndbcluster_binlog_terminating" set when shutting down mysqld. + Server main loop should call handlerton function: + + ndbcluster_hton->binlog_func == + ndbcluster_binlog_func(...,BFN_BINLOG_END,...) == + ndbcluster_binlog_end + + at shutdown, which sets the flag. And then server needs to wait for it + to complete. Otherwise binlog will not be complete. + + ndbcluster_hton->panic == ndbcluster_end() will not return until + ndb binlog is completed +*/ static int ndbcluster_binlog_terminating= 0; /* @@ -222,7 +236,7 @@ static void dbug_print_table(const char *info, TABLE *table) - creating the ndb_apply_status table */ static void run_query(THD *thd, char *buf, char *end, - my_bool print_error, my_bool disable_binlog) + const int *no_print_error, my_bool disable_binlog) { ulong save_query_length= thd->query_length; char *save_query= thd->query; @@ -242,11 +256,18 @@ static void run_query(THD *thd, char *buf, char *end, DBUG_PRINT("query", ("%s", thd->query)); mysql_parse(thd, thd->query, thd->query_length, &found_semicolon); - if (print_error && thd->query_error) + if (no_print_error && thd->query_error) { - sql_print_error("NDB: %s: error %s %d %d %d", - buf, thd->net.last_error, thd->net.last_errno, - thd->net.report_error, thd->query_error); + int i; + Thd_ndb *thd_ndb= get_thd_ndb(thd); + for (i= 0; no_print_error[i]; i++) + if (thd_ndb->m_error == no_print_error[i]) + break; + if (!no_print_error[i]) + sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d", + buf, thd->net.last_error, thd->net.last_errno, + thd_ndb->m_error, + thd->net.report_error, thd->query_error); } thd->options= save_thd_options; @@ -488,7 +509,7 @@ static int ndbcluster_reset_logs(THD *thd) char buf[1024]; char *end= strmov(buf, "DELETE FROM " NDB_REP_DB "." NDB_REP_TABLE); - run_query(thd, buf, end, FALSE, TRUE); + run_query(thd, buf, end, NULL, TRUE); DBUG_RETURN(0); } @@ -513,7 +534,7 @@ ndbcluster_binlog_index_purge_file(THD *thd, const char *file) NDB_REP_DB "." NDB_REP_TABLE " WHERE File='"), file), "'"); - run_query(thd, buf, end, FALSE, TRUE); + run_query(thd, buf, end, NULL, TRUE); DBUG_RETURN(0); } @@ -630,7 +651,7 @@ static void ndbcluster_reset_slave(THD *thd) DBUG_ENTER("ndbcluster_reset_slave"); char buf[1024]; char *end= strmov(buf, "DELETE FROM " NDB_REP_DB "." NDB_APPLY_TABLE); - run_query(thd, buf, end, FALSE, TRUE); + run_query(thd, buf, end, NULL, TRUE); DBUG_VOID_RETURN; } @@ -755,7 +776,8 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd) " end_pos BIGINT UNSIGNED NOT NULL, " " PRIMARY KEY USING HASH (server_id) ) ENGINE=NDB"); - run_query(thd, buf, end, TRUE, TRUE); + const int no_print_error[2]= {701, 0}; // do not print error 701 + run_query(thd, buf, end, no_print_error, TRUE); DBUG_RETURN(0); } @@ -811,7 +833,8 @@ static int ndbcluster_create_schema_table(THD *thd) " type INT UNSIGNED NOT NULL," " PRIMARY KEY USING HASH (db,name) ) ENGINE=NDB"); - run_query(thd, buf, end, TRUE, TRUE); + const int no_print_error[2]= {701, 0}; // do not print error 701 + run_query(thd, buf, end, no_print_error, TRUE); DBUG_RETURN(0); } @@ -1919,9 +1942,10 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, /* Drop the database locally if it only contains ndb tables */ if (! ndbcluster_check_if_local_tables_in_db(thd, schema->db)) { + const int no_print_error[1]= {0}; run_query(thd, schema->query, schema->query + schema->query_length, - TRUE, /* print error */ + no_print_error, /* print error */ TRUE); /* don't binlog the query */ /* binlog dropping database after any table operations */ post_epoch_log_list->push_back(schema, mem_root); @@ -1941,12 +1965,15 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, case SOT_CREATE_DB: /* fall through */ case SOT_ALTER_DB: + { + const int no_print_error[1]= {0}; run_query(thd, schema->query, schema->query + schema->query_length, - TRUE, /* print error */ + no_print_error, /* print error */ TRUE); /* don't binlog the query */ log_query= 1; break; + } case SOT_TABLESPACE: case SOT_LOGFILE_GROUP: log_query= 1; |