only reset tx active_scn to enable recgnize first stmt retry

This commit is contained in:
obdev 2024-02-08 11:07:13 +00:00 committed by ob-robot
parent cfe4eeda1c
commit 9474ff14d4
4 changed files with 23 additions and 24 deletions

View File

@ -1098,7 +1098,9 @@ int ObSqlTransControl::end_stmt(ObExecContext &exec_ctx, const bool rollback)
#else
if (OB_FAIL(ret) || rollback) { print_log = true; }
#endif
if (print_log && OB_NOT_NULL(session)) {
if (print_log
&& OB_NOT_NULL(session)
&& OB_TRY_LOCK_ROW_CONFLICT != exec_ctx.get_errcode()) {
LOG_INFO("end stmt", K(ret),
"plain_select", is_plain_select,
"stmt_type", stmt_type,

View File

@ -680,6 +680,15 @@ int ObTxDesc::update_part_(ObTxPart &a, const bool append)
break;
}
}
if (ObTxDesc::State::IMPLICIT_ACTIVE == state_ && !active_scn_.is_valid()) {
/*
* it is a first stmt's retry, we should set active scn
* to enable recognizing it is first stmt
*/
active_scn_ = get_tx_seq();
}
if (!hit) {
if (append) {
a.last_touch_ts_ = exec_info_reap_ts_ + 1;
@ -755,15 +764,8 @@ void ObTxDesc::implicit_start_tx_()
{
if (parts_.count() > 0 && state_ == ObTxDesc::State::IDLE) {
state_ = ObTxDesc::State::IMPLICIT_ACTIVE;
if (expire_ts_ == INT64_MAX ) {
/*
* To calculate transaction's execution time
* and determine whether transaction has timeout
* just set active_ts and expire_ts on stmt's first execution
*/
active_ts_ = ObClockGenerator::getClock();
expire_ts_ = active_ts_ + timeout_us_;
}
active_ts_ = ObClockGenerator::getClock();
expire_ts_ = active_ts_ + timeout_us_;
active_scn_ = get_tx_seq();
state_change_flags_.mark_all();
}

View File

@ -1136,7 +1136,7 @@ int ObTransService::rollback_to_global_implicit_savepoint_(ObTxDesc &tx,
int ret = OB_SUCCESS;
int64_t start_ts = ObTimeUtility::current_time();
tx.inc_op_sn();
bool reset_tx = false, normal_rollback = false, reset_tx_state = false;
bool reset_tx = false, normal_rollback = false, reset_active_scn = false;
// merge extra touched ls
if (OB_NOT_NULL(extra_touched_ls) && !extra_touched_ls->empty()) {
if (OB_FAIL(tx.update_parts(*extra_touched_ls))) {
@ -1164,13 +1164,13 @@ int ObTransService::rollback_to_global_implicit_savepoint_(ObTxDesc &tx,
&& tx.active_scn_ >= savepoint // rollback all dirty state
&& !tx.has_extra_state_()) { // hasn't explicit savepoint or serializable snapshot
/*
* if sql execute error code don't need reset(abort) tx but need rollback stmt and retry
* if sql execute error code don't need reset(abort) tx but need retry
* e.g. "lock conflict error"
* to ensure next retry can still recognize it is first stmt in transaction
* we should reset tx state
* to ensure next retry can still recognize it is the first stmt in transaction
* we should reset tx's acitve_scn
*/
reset_tx = true; // tx_need_reset_(exec_errcode);
reset_tx_state = !reset_tx;
reset_tx = tx_need_reset_(exec_errcode);
reset_active_scn = !reset_tx;
normal_rollback = !reset_tx;
} else {
normal_rollback = true;
@ -1207,10 +1207,7 @@ int ObTransService::rollback_to_global_implicit_savepoint_(ObTxDesc &tx,
tx.inc_op_sn();
abort_tx_(tx, ObTxAbortCause::SAVEPOINT_ROLLBACK_FAIL);
} else {
if (reset_tx_state) {
// first stmt retry need reset tx state
tx.state_ = ObTxDesc::State::IDLE;
tx.parts_.reset();
if (reset_active_scn) {
tx.active_scn_.reset();
}
/*

View File

@ -321,8 +321,7 @@ TEST_F(ObTestTx, rollback_savepoint_with_need_retry_error)
ASSERT_TRUE(sp.is_valid());
ASSERT_EQ(OB_SUCCESS, n1->write(tx, snapshot, 100, 200));
ASSERT_EQ(OB_SUCCESS, n1->rollback_to_implicit_savepoint(tx, sp, n1->ts_after_ms(5), nullptr, OB_TRANSACTION_SET_VIOLATION));
ASSERT_EQ(ObTxDesc::State::IDLE, tx.state_);
ASSERT_EQ(0, tx.parts_.count());
ASSERT_EQ(ObTxDesc::State::IMPLICIT_ACTIVE, tx.state_);
ASSERT_EQ(ObTxSEQ::INVL(), tx.active_scn_);
ASSERT_EQ(OB_SUCCESS, n1->rollback_to_implicit_savepoint(tx, sp, n1->ts_after_ms(5), nullptr));
}
@ -332,8 +331,7 @@ TEST_F(ObTestTx, rollback_savepoint_with_need_retry_error)
ASSERT_TRUE(sp.is_valid());
ASSERT_EQ(OB_SUCCESS, n1->write(tx, snapshot, 100, 200));
ASSERT_EQ(OB_SUCCESS, n1->rollback_to_implicit_savepoint(tx, sp, n1->ts_after_ms(5), nullptr, OB_TRY_LOCK_ROW_CONFLICT));
ASSERT_EQ(ObTxDesc::State::IDLE, tx.state_);
ASSERT_EQ(0, tx.parts_.count());
ASSERT_EQ(ObTxDesc::State::IMPLICIT_ACTIVE, tx.state_);
ASSERT_EQ(ObTxSEQ::INVL(), tx.active_scn_);
ASSERT_EQ(OB_SUCCESS, n1->rollback_to_implicit_savepoint(tx, sp, n1->ts_after_ms(5), nullptr));
}