[CP] to issue<54683599>:adjust snapshot check logic when fetch cursor

This commit is contained in:
obdev
2024-02-23 07:16:34 +00:00
committed by ob-robot
parent f667ad87d9
commit 731d274e5a
6 changed files with 49 additions and 30 deletions

View File

@ -4143,22 +4143,38 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx,
if (OB_FAIL(ret)) { if (OB_FAIL(ret)) {
} else if (cursor->is_need_check_snapshot()) { /* case: select * from dual, snapshot do not initilize, so it's invalid */ } else if (cursor->is_need_check_snapshot()) { /* case: select * from dual, snapshot do not initilize, so it's invalid */
/* 流式场景:
非for update skip lock:isvalid=false,或者commited=true,则报错
for update skip lock检查逻辑和for update一致
非流式场景:
forupdate:isvalid=false,或者commited=true,则报错,否则继续检查事务状态
非forupdate,直接看isvalid是否为true */
if (lib::is_oracle_mode()) { if (lib::is_oracle_mode()) {
if (!cursor->get_snapshot().valid_) { if (cursor->is_for_update()) {
if (!cursor->get_snapshot().is_valid() || cursor->get_snapshot().is_committed()) {
ret = OB_ERR_FETCH_OUT_SEQUENCE;
LOG_WARN("snapshot is invalid", K(cursor->get_snapshot()), K(ret));
} else {
transaction::ObTransID tx_id = cursor->get_trans_id();
transaction::ObTransService* txs = MTL(transaction::ObTransService*);
bool tx_active = false;
CK (OB_NOT_NULL(txs));
CK (tx_id.is_valid());
OZ (txs->is_tx_active(tx_id, tx_active), tx_id);
if (OB_SUCC(ret) && !tx_active) {
ret = OB_ERR_FETCH_OUT_SEQUENCE;
LOG_WARN("cursor has been closed because of txn was terminated",
K(ret), K(tx_id), K(cursor->get_snapshot()));
}
}
} else if (cursor->is_streaming()) {
if (!cursor->get_snapshot().is_valid() || cursor->get_snapshot().is_committed()) {
ret = OB_ERR_FETCH_OUT_SEQUENCE;
LOG_WARN("snapshot is invalid", K(cursor->get_snapshot()), K(ret));
}
} else if (!cursor->get_snapshot().is_valid()) {
ret = OB_ERR_FETCH_OUT_SEQUENCE; ret = OB_ERR_FETCH_OUT_SEQUENCE;
LOG_WARN("snapshot is invalid", K(cursor->get_snapshot()), K(ret)); LOG_WARN("snapshot is invalid", K(cursor->get_snapshot()), K(ret));
} else if (cursor->is_for_update()) {
transaction::ObTransID tx_id = cursor->get_trans_id();
transaction::ObTransService* txs = MTL(transaction::ObTransService*);
bool tx_active = false;
CK (OB_NOT_NULL(txs));
CK (tx_id.is_valid());
OZ (txs->is_tx_active(tx_id, tx_active), tx_id);
if (OB_SUCC(ret) && !tx_active) {
ret = OB_ERR_FETCH_OUT_SEQUENCE;
LOG_WARN("cursor has been closed because of txn was terminated",
K(ret), K(tx_id), K(cursor->get_snapshot()));
}
} }
} }
} }

View File

@ -192,7 +192,8 @@ OB_SERIALIZE_MEMBER(ObTxReadSnapshot,
uncertain_bound_, uncertain_bound_,
snapshot_lsid_, snapshot_lsid_,
parts_, parts_,
snapshot_ls_role_); snapshot_ls_role_,
committed_);
OB_SERIALIZE_MEMBER(ObTxPart, id_, addr_, epoch_, first_scn_, last_scn_); OB_SERIALIZE_MEMBER(ObTxPart, id_, addr_, epoch_, first_scn_, last_scn_);
DEFINE_SERIALIZE(ObTxDesc::FLAG::FOR_FIXED_SER_VAL) DEFINE_SERIALIZE(ObTxDesc::FLAG::FOR_FIXED_SER_VAL)
@ -1160,6 +1161,7 @@ ObTxSnapshot &ObTxSnapshot::operator=(const ObTxSnapshot &r)
ObTxReadSnapshot::ObTxReadSnapshot() ObTxReadSnapshot::ObTxReadSnapshot()
: valid_(false), : valid_(false),
committed_(false),
core_(), core_(),
source_(SRC::INVL), source_(SRC::INVL),
snapshot_lsid_(), snapshot_lsid_(),
@ -1171,6 +1173,7 @@ ObTxReadSnapshot::ObTxReadSnapshot()
ObTxReadSnapshot::~ObTxReadSnapshot() ObTxReadSnapshot::~ObTxReadSnapshot()
{ {
valid_ = false; valid_ = false;
committed_ = false;
source_ = SRC::INVL; source_ = SRC::INVL;
snapshot_ls_role_ = common::INVALID_ROLE; snapshot_ls_role_ = common::INVALID_ROLE;
uncertain_bound_ = 0; uncertain_bound_ = 0;
@ -1179,6 +1182,7 @@ ObTxReadSnapshot::~ObTxReadSnapshot()
void ObTxReadSnapshot::reset() void ObTxReadSnapshot::reset()
{ {
valid_ = false; valid_ = false;
committed_ = false;
core_.reset(); core_.reset();
source_ = SRC::INVL; source_ = SRC::INVL;
snapshot_lsid_.reset(); snapshot_lsid_.reset();
@ -1191,6 +1195,7 @@ int ObTxReadSnapshot::assign(const ObTxReadSnapshot &from)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
valid_ = from.valid_; valid_ = from.valid_;
committed_ = from.committed_;
core_ = from.core_; core_ = from.core_;
source_ = from.source_; source_ = from.source_;
snapshot_lsid_ = from.snapshot_lsid_; snapshot_lsid_ = from.snapshot_lsid_;

View File

@ -248,7 +248,8 @@ struct ObTxSnapshot
// snapshot used to consistency read // snapshot used to consistency read
struct ObTxReadSnapshot struct ObTxReadSnapshot
{ {
bool valid_; bool valid_; // used by cursor check snapshot state
bool committed_; // used by cursor check snapshot state
ObTxSnapshot core_; ObTxSnapshot core_;
enum class SRC { enum class SRC {
INVL = 0, INVL = 0,
@ -275,6 +276,8 @@ struct ObTxReadSnapshot
bool is_none_read() const { return SRC::NONE == source_; } bool is_none_read() const { return SRC::NONE == source_; }
bool is_special() const { return SRC::SPECIAL == source_; } bool is_special() const { return SRC::SPECIAL == source_; }
bool is_ls_snapshot() const { return SRC::LS == source_; } bool is_ls_snapshot() const { return SRC::LS == source_; }
bool is_valid() const { return valid_; }
bool is_committed() const { return committed_; }
int format_source_for_display(char *buf, const int64_t buf_len) const; int format_source_for_display(char *buf, const int64_t buf_len) const;
void reset(); void reset();
int assign(const ObTxReadSnapshot &); int assign(const ObTxReadSnapshot &);
@ -287,7 +290,8 @@ struct ObTxReadSnapshot
K_(uncertain_bound), K_(uncertain_bound),
K_(snapshot_lsid), K_(snapshot_lsid),
K_(snapshot_ls_role), K_(snapshot_ls_role),
K_(parts)); K_(parts),
K_(committed));
OB_UNIS_VERSION(1); OB_UNIS_VERSION(1);
}; };

View File

@ -628,13 +628,17 @@ void ObTransService::invalid_registered_snapshot_(ObTxDesc &tx)
} }
} }
void ObTransService::registered_snapshot_clear_part_(ObTxDesc &tx) void ObTransService::process_registered_snapshot_on_commit_(ObTxDesc &tx)
{ {
// cleanup snapshot's participant info, so that they will skip
// verify participant txn ctx, which cause false negative,
// because txn ctx has quit when txn committed.
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
ARRAY_FOREACH(tx.savepoints_, i) { ARRAY_FOREACH(tx.savepoints_, i) {
ObTxSavePoint &p = tx.savepoints_[i]; ObTxSavePoint &p = tx.savepoints_[i];
if (p.is_snapshot() && p.snapshot_->valid_) { if (p.is_snapshot() && p.snapshot_->valid_) {
p.snapshot_->parts_.reset(); p.snapshot_->parts_.reset();
p.snapshot_->committed_ = true;
} }
} }
} }

View File

@ -347,7 +347,7 @@ int update_user_savepoint_(ObTxDesc &tx, const ObTxSavePointList &savepoints);
private: private:
ObTxCtxMgr tx_ctx_mgr_; ObTxCtxMgr tx_ctx_mgr_;
void invalid_registered_snapshot_(ObTxDesc &tx); void invalid_registered_snapshot_(ObTxDesc &tx);
void registered_snapshot_clear_part_(ObTxDesc &tx); void process_registered_snapshot_on_commit_(ObTxDesc &tx);
int ls_rollback_to_savepoint_(const ObTransID &tx_id, int ls_rollback_to_savepoint_(const ObTransID &tx_id,
const share::ObLSID &ls, const share::ObLSID &ls,
const int64_t verify_epoch, const int64_t verify_epoch,

View File

@ -1907,20 +1907,10 @@ int ObTransService::add_tx_exec_result(ObTxDesc &tx, const ObTxExecResult &exec_
void ObTransService::tx_post_terminate_(ObTxDesc &tx) void ObTransService::tx_post_terminate_(ObTxDesc &tx)
{ {
// invalid registered snapshot // invalid registered snapshot
if (tx.state_ == ObTxDesc::State::ABORTED || if (tx.state_ == ObTxDesc::State::ABORTED || tx.is_commit_unsucc()) {
tx.is_commit_unsucc()
// FIXME: (yunxing.cyx)
// bellow line is temproary, when storage layer support
// record txn-id in SSTable's MvccRow, we can remove this
// (the support was planed in v4.1)
|| tx.state_ == ObTxDesc::State::COMMITTED
) {
invalid_registered_snapshot_(tx); invalid_registered_snapshot_(tx);
} else if (tx.state_ == ObTxDesc::State::COMMITTED) { } else if (tx.state_ == ObTxDesc::State::COMMITTED) {
// cleanup snapshot's participant info, so that they will skip process_registered_snapshot_on_commit_(tx);
// verify participant txn ctx, which cause false negative,
// because txn ctx has quit when txn committed.
registered_snapshot_clear_part_(tx);
} }
// statistic // statistic
if (tx.is_tx_end()) { if (tx.is_tx_end()) {