diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2019-04-18 14:43:40 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2019-04-25 15:06:40 +0400 |
commit | 07140f171d8c81d241ef4fd7e8e53afa2d269b16 (patch) | |
tree | 18201b76c97e4511a9cb8967c11031bec52f6a60 /sql/transaction.cc | |
parent | ca7fbcea6c4fe13c295cf43b80d05351aba59e95 (diff) | |
download | mariadb-git-07140f171d8c81d241ef4fd7e8e53afa2d269b16.tar.gz |
Just move, no code changes otherwise.
Part of MDEV-7974 - backport fix for mysql bug#12161 (XA and binlog)
Diffstat (limited to 'sql/transaction.cc')
-rw-r--r-- | sql/transaction.cc | 332 |
1 files changed, 3 insertions, 329 deletions
diff --git a/sql/transaction.cc b/sql/transaction.cc index 4d61d2a120d..15c45425528 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -28,21 +28,19 @@ #include "wsrep_trans_observer.h" #endif /* WITH_WSREP */ -#ifndef EMBEDDED_LIBRARY /** Helper: Tell tracker (if any) that transaction ended. */ -static void trans_track_end_trx(THD *thd) +void trans_track_end_trx(THD *thd) { +#ifndef EMBEDDED_LIBRARY if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) { ((Transaction_state_tracker *) thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER))->end_trx(thd); } -} -#else -#define trans_track_end_trx(A) do{}while(0) #endif //EMBEDDED_LIBRARY +} /** @@ -89,65 +87,6 @@ static bool trans_check(THD *thd) /** - Mark a XA transaction as rollback-only if the RM unilaterally - rolled back the transaction branch. - - @note If a rollback was requested by the RM, this function sets - the appropriate rollback error code and transits the state - to XA_ROLLBACK_ONLY. - - @return TRUE if transaction was rolled back or if the transaction - state is XA_ROLLBACK_ONLY. FALSE otherwise. -*/ -static bool xa_trans_rolled_back(XID_STATE *xid_state) -{ - if (xid_state->rm_error) - { - switch (xid_state->rm_error) { - case ER_LOCK_WAIT_TIMEOUT: - my_error(ER_XA_RBTIMEOUT, MYF(0)); - break; - case ER_LOCK_DEADLOCK: - my_error(ER_XA_RBDEADLOCK, MYF(0)); - break; - default: - my_error(ER_XA_RBROLLBACK, MYF(0)); - } - xid_state->xa_state= XA_ROLLBACK_ONLY; - } - - return (xid_state->xa_state == XA_ROLLBACK_ONLY); -} - - -/** - Rollback the active XA transaction. - - @note Resets rm_error before calling ha_rollback(), so - the thd->transaction.xid structure gets reset - by ha_rollback() / THD::transaction::cleanup(). - - @return TRUE if the rollback failed, FALSE otherwise. -*/ - -static bool xa_trans_force_rollback(THD *thd) -{ - /* - We must reset rm_error before calling ha_rollback(), - so thd->transaction.xid structure gets reset - by ha_rollback()/THD::transaction::cleanup(). - */ - thd->transaction.xid_state.rm_error= 0; - if (ha_rollback_trans(thd, true)) - { - my_error(ER_XAER_RMERR, MYF(0)); - return true; - } - return false; -} - - -/** Begin a new transaction. @note Beginning a transaction implicitly commits any current @@ -777,268 +716,3 @@ bool trans_release_savepoint(THD *thd, LEX_CSTRING name) DBUG_RETURN(MY_TEST(res)); } - - -/** - Starts an XA transaction with the given xid value. - - @param thd Current thread - - @retval FALSE Success - @retval TRUE Failure -*/ - -bool trans_xa_start(THD *thd) -{ - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - DBUG_ENTER("trans_xa_start"); - - if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME) - { - bool not_equal= !thd->transaction.xid_state.xid.eq(thd->lex->xid); - if (not_equal) - my_error(ER_XAER_NOTA, MYF(0)); - else - thd->transaction.xid_state.xa_state= XA_ACTIVE; - DBUG_RETURN(not_equal); - } - - /* TODO: JOIN is not supported yet. */ - if (thd->lex->xa_opt != XA_NONE) - my_error(ER_XAER_INVAL, MYF(0)); - else if (xa_state != XA_NOTR) - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); - else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) - my_error(ER_XAER_OUTSIDE, MYF(0)); - else if (!trans_begin(thd)) - { - DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); - thd->transaction.xid_state.xa_state= XA_ACTIVE; - thd->transaction.xid_state.rm_error= 0; - thd->transaction.xid_state.xid.set(thd->lex->xid); - if (xid_cache_insert(thd, &thd->transaction.xid_state)) - { - thd->transaction.xid_state.xa_state= XA_NOTR; - thd->transaction.xid_state.xid.null(); - trans_rollback(thd); - DBUG_RETURN(true); - } - DBUG_RETURN(FALSE); - } - - DBUG_RETURN(TRUE); -} - - -/** - Put a XA transaction in the IDLE state. - - @param thd Current thread - - @retval FALSE Success - @retval TRUE Failure -*/ - -bool trans_xa_end(THD *thd) -{ - DBUG_ENTER("trans_xa_end"); - - /* TODO: SUSPEND and FOR MIGRATE are not supported yet. */ - if (thd->lex->xa_opt != XA_NONE) - my_error(ER_XAER_INVAL, MYF(0)); - else if (thd->transaction.xid_state.xa_state != XA_ACTIVE) - my_error(ER_XAER_RMFAIL, MYF(0), - xa_state_names[thd->transaction.xid_state.xa_state]); - else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) - my_error(ER_XAER_NOTA, MYF(0)); - else if (!xa_trans_rolled_back(&thd->transaction.xid_state)) - thd->transaction.xid_state.xa_state= XA_IDLE; - - DBUG_RETURN(thd->is_error() || - thd->transaction.xid_state.xa_state != XA_IDLE); -} - - -/** - Put a XA transaction in the PREPARED state. - - @param thd Current thread - - @retval FALSE Success - @retval TRUE Failure -*/ - -bool trans_xa_prepare(THD *thd) -{ - DBUG_ENTER("trans_xa_prepare"); - - if (thd->transaction.xid_state.xa_state != XA_IDLE) - my_error(ER_XAER_RMFAIL, MYF(0), - xa_state_names[thd->transaction.xid_state.xa_state]); - else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) - my_error(ER_XAER_NOTA, MYF(0)); - else if (ha_prepare(thd)) - { - xid_cache_delete(thd, &thd->transaction.xid_state); - thd->transaction.xid_state.xa_state= XA_NOTR; - my_error(ER_XA_RBROLLBACK, MYF(0)); - } - else - thd->transaction.xid_state.xa_state= XA_PREPARED; - - DBUG_RETURN(thd->is_error() || - thd->transaction.xid_state.xa_state != XA_PREPARED); -} - - -/** - Commit and terminate the a XA transaction. - - @param thd Current thread - - @retval FALSE Success - @retval TRUE Failure -*/ - -bool trans_xa_commit(THD *thd) -{ - bool res= TRUE; - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - DBUG_ENTER("trans_xa_commit"); - - if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) - { - if (thd->fix_xid_hash_pins()) - { - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - DBUG_RETURN(TRUE); - } - - XID_STATE *xs= xid_cache_search(thd, thd->lex->xid); - res= !xs; - if (res) - my_error(ER_XAER_NOTA, MYF(0)); - else - { - res= xa_trans_rolled_back(xs); - ha_commit_or_rollback_by_xid(thd->lex->xid, !res); - xid_cache_delete(thd, xs); - } - DBUG_RETURN(res); - } - - if (xa_trans_rolled_back(&thd->transaction.xid_state)) - { - xa_trans_force_rollback(thd); - res= thd->is_error(); - } - else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) - { - int r= ha_commit_trans(thd, TRUE); - if ((res= MY_TEST(r))) - my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); - } - else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE) - { - MDL_request mdl_request; - - /* - Acquire metadata lock which will ensure that COMMIT is blocked - by active FLUSH TABLES WITH READ LOCK (and vice versa COMMIT in - progress blocks FTWRL). - - We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does. - */ - mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, - MDL_TRANSACTION); - - if (thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) - { - ha_rollback_trans(thd, TRUE); - my_error(ER_XAER_RMERR, MYF(0)); - } - else - { - DEBUG_SYNC(thd, "trans_xa_commit_after_acquire_commit_lock"); - - res= MY_TEST(ha_commit_one_phase(thd, 1)); - if (res) - my_error(ER_XAER_RMERR, MYF(0)); - } - } - else - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); - DBUG_RETURN(TRUE); - } - - thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); - thd->server_status&= - ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); - DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); - xid_cache_delete(thd, &thd->transaction.xid_state); - thd->transaction.xid_state.xa_state= XA_NOTR; - - trans_track_end_trx(thd); - - DBUG_RETURN(res); -} - - -/** - Roll back and terminate a XA transaction. - - @param thd Current thread - - @retval FALSE Success - @retval TRUE Failure -*/ - -bool trans_xa_rollback(THD *thd) -{ - bool res= TRUE; - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - DBUG_ENTER("trans_xa_rollback"); - - if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) - { - if (thd->fix_xid_hash_pins()) - { - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - DBUG_RETURN(TRUE); - } - - XID_STATE *xs= xid_cache_search(thd, thd->lex->xid); - if (!xs) - my_error(ER_XAER_NOTA, MYF(0)); - else - { - xa_trans_rolled_back(xs); - ha_commit_or_rollback_by_xid(thd->lex->xid, 0); - xid_cache_delete(thd, xs); - } - DBUG_RETURN(thd->get_stmt_da()->is_error()); - } - - if (xa_state != XA_IDLE && xa_state != XA_PREPARED && xa_state != XA_ROLLBACK_ONLY) - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); - DBUG_RETURN(TRUE); - } - - res= xa_trans_force_rollback(thd); - - thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); - thd->server_status&= - ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); - DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); - xid_cache_delete(thd, &thd->transaction.xid_state); - thd->transaction.xid_state.xa_state= XA_NOTR; - - trans_track_end_trx(thd); - - DBUG_RETURN(res); -} |