From 9bcdbcde5e648cd51e4324088b13bd51d44641f8 Mon Sep 17 00:00:00 2001 From: obdev Date: Wed, 22 Mar 2023 11:49:24 +0000 Subject: [PATCH] [4.1][savepoint] stop rollback to savepoint when trans is terminated --- src/storage/tx/ob_tx_api.cpp | 15 +++++++++++++-- src/storage/tx/ob_xa_service.cpp | 20 ++++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/storage/tx/ob_tx_api.cpp b/src/storage/tx/ob_tx_api.cpp index 9f35f30c57..1c967d0e03 100644 --- a/src/storage/tx/ob_tx_api.cpp +++ b/src/storage/tx/ob_tx_api.cpp @@ -1571,8 +1571,19 @@ inline int ObTransService::sync_rollback_savepoint__(ObTxDesc &tx, int rpc_ret = OB_SUCCESS; if (OB_FAIL(tx.rpc_cond_.wait(waittime, rpc_ret))) { TRANS_LOG(WARN, "tx rpc condition wakeup", K(ret), - K(waittime), K(rpc_ret), K(expire_ts), K(remain), K(remain_cnt), K(retries)); - ret = OB_SUCCESS; + K(waittime), K(rpc_ret), K(expire_ts), K(remain), K(remain_cnt), K(retries), + K_(tx.state)); + // if trans is terminated, rollback savepoint should be terminated + // NOTE that this case is only for xa trans + // EXAMPLE, tx desc is shared by branch 1 and branch 2 + // 1. branch 1 starts to rollback savepoint + // 2. branch 2 is terminated + // 3. branch 1 receives callback of rollback savepoint + if (tx.is_terminated()) { + ret = OB_TRANS_HAS_DECIDED; + } else { + ret = OB_SUCCESS; + } } if (OB_SUCCESS != rpc_ret) { TRANS_LOG(WARN, "tx rpc fail", K(rpc_ret), K_(tx.tx_id), K(waittime), K(remain), K(remain_cnt), K(retries)); diff --git a/src/storage/tx/ob_xa_service.cpp b/src/storage/tx/ob_xa_service.cpp index 018ce8378e..77ae806b70 100644 --- a/src/storage/tx/ob_xa_service.cpp +++ b/src/storage/tx/ob_xa_service.cpp @@ -2209,20 +2209,28 @@ int ObXAService::terminate_to_original_(const ObXATransID &xid, int ObXAService::xa_rollback_all_changes(const ObXATransID &xid, ObTxDesc *&tx_desc, const int64_t stmt_expired_time) { int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; const int64_t savepoint = 1; if (NULL == tx_desc || !tx_desc->is_valid() || !xid.is_valid() || stmt_expired_time < 0) { ret = OB_INVALID_ARGUMENT; TRANS_LOG(WARN, "invalid argument", K(ret), KP(tx_desc), K(xid), K(stmt_expired_time)); } else { + ObTransID tx_id = tx_desc->get_tx_id(); if (OB_FAIL(start_stmt(xid, 0/*unused session id*/, *tx_desc))) { - TRANS_LOG(WARN, "xa start stmt fail", K(ret), K(tx_desc), K(xid)); - } else if (OB_FAIL(MTL(transaction::ObTransService *)->rollback_to_implicit_savepoint(*tx_desc, savepoint, stmt_expired_time, NULL))) { - TRANS_LOG(WARN, "do savepoint rollback error", K(ret), K(tx_desc)); - } else if (OB_FAIL(end_stmt(xid, *tx_desc))) { - TRANS_LOG(WARN, "xa start stmt fail", K(ret), K(tx_desc), K(xid)); + TRANS_LOG(WARN, "xa start stmt fail", K(ret), K(xid), K(tx_id)); } else { - TRANS_LOG(INFO, "xa rollback all changes success", K(ret), K(tx_desc), K(xid)); + if (OB_FAIL(MTL(transaction::ObTransService *)->rollback_to_implicit_savepoint(*tx_desc, + savepoint, stmt_expired_time, NULL))) { + TRANS_LOG(WARN, "do savepoint rollback error", K(ret), K(xid), K(tx_id)); + } else { + TRANS_LOG(INFO, "xa rollback all changes success", K(ret), K(xid), K(tx_id)); + } + if (OB_SUCCESS != (tmp_ret = end_stmt(xid, *tx_desc))) { + // return the error code of end stmt first + ret = tmp_ret; + TRANS_LOG(WARN, "xa end stmt fail", K(ret), K(xid), K(tx_id)); + } } } return ret; -- GitLab