diff --git a/src/storage/memtable/mvcc/ob_mvcc_acc_ctx.h b/src/storage/memtable/mvcc/ob_mvcc_acc_ctx.h index 7ddfd1dff9..1e8b029a28 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_acc_ctx.h +++ b/src/storage/memtable/mvcc/ob_mvcc_acc_ctx.h @@ -51,6 +51,7 @@ public: tx_scn_(-1), write_flag_(), handle_start_time_(OB_INVALID_TIMESTAMP), + is_standby_read_(false), lock_wait_start_ts_(0) {} ~ObMvccAccessCtx() { @@ -64,6 +65,7 @@ public: tx_scn_ = -1; write_flag_.reset(); handle_start_time_ = OB_INVALID_TIMESTAMP; + is_standby_read_ = false; } void reset() { if (is_write() && OB_UNLIKELY(tx_ctx_)) { @@ -81,6 +83,7 @@ public: tx_scn_ = -1; write_flag_.reset(); handle_start_time_ = OB_INVALID_TIMESTAMP; + is_standby_read_ = false; } bool is_valid() const { switch(type_) { @@ -256,6 +259,8 @@ public: // NOTE: those field should only be accessed by txn relative routine // this was used for runtime mertic int64_t handle_start_time_; + + bool is_standby_read_; protected: int64_t lock_wait_start_ts_; }; diff --git a/src/storage/memtable/mvcc/ob_mvcc_iterator.cpp b/src/storage/memtable/mvcc/ob_mvcc_iterator.cpp index 8bc94b6fe8..404af9416e 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_iterator.cpp +++ b/src/storage/memtable/mvcc/ob_mvcc_iterator.cpp @@ -228,6 +228,7 @@ int ObMvccValueIterator::lock_for_read_inner_(const ObQueryFlag &flag, // snapshot int counter = 0; while (OB_SUCC(ret) + && !ctx_->is_standby_read_ && is_determined_state && !(iter->is_committed() || iter->is_aborted() || iter->is_elr())) { if (OB_FAIL(try_cleanout_tx_node_(iter))) { diff --git a/src/storage/memtable/ob_memtable_iterator.cpp b/src/storage/memtable/ob_memtable_iterator.cpp index f4e824484f..2834989582 100644 --- a/src/storage/memtable/ob_memtable_iterator.cpp +++ b/src/storage/memtable/ob_memtable_iterator.cpp @@ -1440,8 +1440,8 @@ OB_INLINE int ObReadRow::iterate_row_value_( const ObTransID snapshot_tx_id = value_iter.get_snapshot_tx_id(); const ObTransID reader_tx_id = value_iter.get_reader_tx_id(); row_scn = tx_node->trans_version_.get_val_for_tx(); - if (!(snapshot_tx_id == tx_node->get_tx_id() || reader_tx_id == tx_node->get_tx_id()) - && tx_node->trans_version_.is_max()) { + if (!value_iter.get_mvcc_acc_ctx()->is_standby_read_ && (!(snapshot_tx_id == tx_node->get_tx_id() || reader_tx_id == tx_node->get_tx_id()) + && tx_node->trans_version_.is_max())) { TRANS_LOG(ERROR, "meet row scn with undecided value", KPC(tx_node), K(is_committed), K(trans_version), K(value_iter)); } diff --git a/src/storage/tx/ob_tx_data_functor.cpp b/src/storage/tx/ob_tx_data_functor.cpp index 79d063a6d2..38fe8faf76 100644 --- a/src/storage/tx/ob_tx_data_functor.cpp +++ b/src/storage/tx/ob_tx_data_functor.cpp @@ -375,9 +375,13 @@ int LockForReadFunctor::operator()(const ObTxData &tx_data, ObTxCCCtx *tx_cc_ctx int LockForReadFunctor::check_for_standby(const transaction::ObTransID &tx_id) { - return MTL(transaction::ObTransService *)->check_for_standby(ls_id_, tx_id, - lock_for_read_arg_.mvcc_acc_ctx_.snapshot_.version_, - can_read_, trans_version_, is_determined_state_); + int ret = OB_SUCCESS; + if (OB_SUCC(MTL(transaction::ObTransService *)->check_for_standby(ls_id_, tx_id, + lock_for_read_arg_.mvcc_acc_ctx_.snapshot_.version_, + can_read_, trans_version_, is_determined_state_))) { + lock_for_read_arg_.mvcc_acc_ctx_.is_standby_read_ = true; + } + return ret; } int CleanoutTxStateFunctor::operator()(const ObTxData &tx_data, ObTxCCCtx *tx_cc_ctx)