diff options
Diffstat (limited to 'sql/wsrep_mysqld.cc')
-rw-r--r-- | sql/wsrep_mysqld.cc | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 6692e8c4ef0..444a187ea57 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -292,7 +292,7 @@ static void wsrep_log_cb(wsrep::log::level level, const char *msg) sql_print_warning("WSREP: %s", msg); break; case wsrep::log::error: - sql_print_error("WSREP: %s", msg); + sql_print_error("WSREP: %s", msg); break; case wsrep::log::debug: if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); @@ -1840,13 +1840,16 @@ static void wsrep_TOI_begin_failed(THD* thd, const wsrep_buf_t* /* const err */) if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); if (wsrep_write_dummy_event(thd, "TOI begin failed")) { goto fail; } wsrep::client_state& cs(thd->wsrep_cs()); - int const ret= cs.leave_toi_local(wsrep::mutable_buffer()); + std::string const err(wsrep::to_c_string(cs.current_error())); + wsrep::mutable_buffer err_buf; + err_buf.push_back(err); + int const ret= cs.leave_toi_local(err_buf); if (ret) { WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %lld, " "schema: %s, SQL: %s, rcode: %d wsrep_error: %s", (long long)thd->real_id, thd->db.str, - thd->query(), ret, wsrep::to_c_string(cs.current_error())); + thd->query(), ret, err.c_str()); goto fail; } } @@ -1965,7 +1968,12 @@ static void wsrep_TOI_end(THD *thd) { if (wsrep_thd_is_local_toi(thd)) { wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); - int ret= client_state.leave_toi_local(wsrep::mutable_buffer()); + wsrep::mutable_buffer err; + if (thd->is_error() && !wsrep_must_ignore_error(thd)) + { + wsrep_store_error(thd, err); + } + int const ret= client_state.leave_toi_local(err); if (!ret) { WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get()); @@ -2465,7 +2473,7 @@ int wsrep_must_ignore_error(THD* thd) const uint flags= sql_command_flags[thd->lex->sql_command]; DBUG_ASSERT(error); - DBUG_ASSERT(wsrep_thd_is_toi(thd) || wsrep_thd_is_applying(thd)); + DBUG_ASSERT(wsrep_thd_is_toi(thd)); if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_DDL)) goto ignore_error; @@ -2683,13 +2691,6 @@ void* start_wsrep_THD(void *arg) mysql_thread_set_psi_id(thd->thread_id); thd->thr_create_utime= microsecond_interval_timer(); - if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - goto error; - } // </5.1.17> /* @@ -2710,7 +2711,7 @@ void* start_wsrep_THD(void *arg) { close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + unlink_thd(thd); delete thd; delete thd_args; goto error; @@ -2786,7 +2787,7 @@ void* start_wsrep_THD(void *arg) if (plugins_are_initialized) { net_end(&thd->net); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); + unlink_thd(thd); } else { @@ -2795,9 +2796,9 @@ void* start_wsrep_THD(void *arg) 'Error in my_thread_global_end(): 2 threads didn't exit' at server shutdown */ + server_threads.erase(thd); } - server_threads.erase(thd); delete thd; my_thread_end(); return(NULL); @@ -2836,3 +2837,54 @@ bool wsrep_consistency_check(THD *thd) { return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; } + + +/* + Commit an empty transaction. + + If the transaction is real and the wsrep transaction is still active, + the transaction did not generate any rows or keys and is committed + as empty. Here the wsrep transaction is rolled back and after statement + step is performed to leave the wsrep transaction in the state as it + never existed. + + This should not be an inline functions as it requires a lot of stack space + because of WSREP_DBUG() usage. It's also not a function that is + frequently called. +*/ + +void wsrep_commit_empty(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_commit_empty"); + WSREP_DEBUG("wsrep_commit_empty(%llu)", thd->thread_id); + if (wsrep_is_real(thd, all) && + wsrep_thd_is_local(thd) && + thd->wsrep_trx().active() && + thd->wsrep_trx().state() != wsrep::transaction::s_committed) + { + /* @todo CTAS with STATEMENT binlog format and empty result set + seems to be committing empty. Figure out why and try to fix + elsewhere. */ + DBUG_ASSERT(!wsrep_has_changes(thd) || + (thd->lex->sql_command == SQLCOM_CREATE_TABLE && + !thd->is_current_stmt_binlog_format_row())); + bool have_error= wsrep_current_error(thd); + int ret= wsrep_before_rollback(thd, all) || + wsrep_after_rollback(thd, all) || + wsrep_after_statement(thd); + /* The committing transaction was empty but it held some locks and + got BF aborted. As there were no certified changes in the + data, we ignore the deadlock error and rely on error reporting + by storage engine/server. */ + if (!ret && !have_error && wsrep_current_error(thd)) + { + DBUG_ASSERT(wsrep_current_error(thd) == wsrep::e_deadlock_error); + thd->wsrep_cs().reset_error(); + } + if (ret) + { + WSREP_DEBUG("wsrep_commit_empty failed: %d", wsrep_current_error(thd)); + } + } + DBUG_VOID_RETURN; +} |