[BUG] fix 4138 because unclear session timestamp
This commit is contained in:
@ -560,6 +560,16 @@ int ObSqlTransControl::start_stmt(ObExecContext &exec_ctx)
|
|||||||
LOG_WARN("call sql stmt end hook fail", K(tmp_ret));
|
LOG_WARN("call sql stmt end hook fail", K(tmp_ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OB_SUCC(ret)
|
||||||
|
&& !ObSQLUtils::is_nested_sql(&exec_ctx)
|
||||||
|
&& das_ctx.get_snapshot().core_.version_.is_valid()) {
|
||||||
|
// maintain the read snapshot version on session for multi-version garbage
|
||||||
|
// colloecor. It is maintained for all cases except remote exection with ac
|
||||||
|
// = 1. So we need carefully design the version for the corner case.
|
||||||
|
session->set_reserved_snapshot_version(das_ctx.get_snapshot().core_.version_);
|
||||||
|
}
|
||||||
|
|
||||||
bool print_log = false;
|
bool print_log = false;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
print_log = true;
|
print_log = true;
|
||||||
@ -911,6 +921,10 @@ int ObSqlTransControl::end_stmt(ObExecContext &exec_ctx, const bool rollback)
|
|||||||
ret = COVER_SUCC(tmp_ret);
|
ret = COVER_SUCC(tmp_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OB_SUCC(ret) && !ObSQLUtils::is_nested_sql(&exec_ctx)) {
|
||||||
|
session->reset_reserved_snapshot_version();
|
||||||
|
}
|
||||||
|
|
||||||
bool print_log = false;
|
bool print_log = false;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
print_log = true;
|
print_log = true;
|
||||||
|
|||||||
@ -70,7 +70,7 @@ ObBasicSessionInfo::ObBasicSessionInfo()
|
|||||||
sys_var_base_version_(OB_INVALID_VERSION),
|
sys_var_base_version_(OB_INVALID_VERSION),
|
||||||
tx_desc_(NULL),
|
tx_desc_(NULL),
|
||||||
tx_result_(),
|
tx_result_(),
|
||||||
unused_read_snapshot_version_(),
|
reserved_read_snapshot_version_(),
|
||||||
xid_(),
|
xid_(),
|
||||||
associated_xa_(false),
|
associated_xa_(false),
|
||||||
cached_tenant_config_version_(0),
|
cached_tenant_config_version_(0),
|
||||||
@ -404,7 +404,7 @@ void ObBasicSessionInfo::reset(bool skip_sys_var)
|
|||||||
sys_var_base_version_ = CACHED_SYS_VAR_VERSION;
|
sys_var_base_version_ = CACHED_SYS_VAR_VERSION;
|
||||||
}
|
}
|
||||||
curr_trans_last_stmt_end_time_ = 0;
|
curr_trans_last_stmt_end_time_ = 0;
|
||||||
unused_read_snapshot_version_.reset();
|
reserved_read_snapshot_version_.reset();
|
||||||
check_sys_variable_ = true;
|
check_sys_variable_ = true;
|
||||||
is_foreign_key_cascade_ = false;
|
is_foreign_key_cascade_ = false;
|
||||||
is_foreign_key_check_exist_ = false;
|
is_foreign_key_check_exist_ = false;
|
||||||
@ -4258,7 +4258,7 @@ OB_DEF_SERIALIZE(ObBasicSessionInfo)
|
|||||||
nested_count_,
|
nested_count_,
|
||||||
thread_data_.user_name_,
|
thread_data_.user_name_,
|
||||||
next_tx_isolation_,
|
next_tx_isolation_,
|
||||||
unused_read_snapshot_version_,
|
reserved_read_snapshot_version_,
|
||||||
check_sys_variable_,
|
check_sys_variable_,
|
||||||
unused_weak_read_snapshot_source,
|
unused_weak_read_snapshot_source,
|
||||||
database_id_,
|
database_id_,
|
||||||
@ -4453,7 +4453,7 @@ OB_DEF_DESERIALIZE(ObBasicSessionInfo)
|
|||||||
nested_count_,
|
nested_count_,
|
||||||
thread_data_.user_name_,
|
thread_data_.user_name_,
|
||||||
next_tx_isolation_,
|
next_tx_isolation_,
|
||||||
unused_read_snapshot_version_,
|
reserved_read_snapshot_version_,
|
||||||
check_sys_variable_,
|
check_sys_variable_,
|
||||||
unused_weak_read_snapshot_source,
|
unused_weak_read_snapshot_source,
|
||||||
database_id_,
|
database_id_,
|
||||||
@ -4770,7 +4770,7 @@ OB_DEF_SERIALIZE_SIZE(ObBasicSessionInfo)
|
|||||||
nested_count_,
|
nested_count_,
|
||||||
thread_data_.user_name_,
|
thread_data_.user_name_,
|
||||||
next_tx_isolation_,
|
next_tx_isolation_,
|
||||||
unused_read_snapshot_version_,
|
reserved_read_snapshot_version_,
|
||||||
check_sys_variable_,
|
check_sys_variable_,
|
||||||
unused_weak_read_snapshot_source,
|
unused_weak_read_snapshot_source,
|
||||||
database_id_,
|
database_id_,
|
||||||
|
|||||||
@ -1237,6 +1237,9 @@ public:
|
|||||||
void set_is_in_user_scope(bool value) { sql_scope_flags_.set_is_in_user_scope(value); }
|
void set_is_in_user_scope(bool value) { sql_scope_flags_.set_is_in_user_scope(value); }
|
||||||
bool is_in_user_scope() const { return sql_scope_flags_.is_in_user_scope(); }
|
bool is_in_user_scope() const { return sql_scope_flags_.is_in_user_scope(); }
|
||||||
SqlScopeFlags &get_sql_scope_flags() { return sql_scope_flags_; }
|
SqlScopeFlags &get_sql_scope_flags() { return sql_scope_flags_; }
|
||||||
|
share::SCN get_reserved_snapshot_version() const { return reserved_read_snapshot_version_; }
|
||||||
|
void set_reserved_snapshot_version(const share::SCN snapshot_version) { reserved_read_snapshot_version_ = snapshot_version; }
|
||||||
|
void reset_reserved_snapshot_version() { reserved_read_snapshot_version_.reset(); }
|
||||||
|
|
||||||
bool get_check_sys_variable() { return check_sys_variable_; }
|
bool get_check_sys_variable() { return check_sys_variable_; }
|
||||||
void set_check_sys_variable(bool check_sys_variable) { check_sys_variable_ = check_sys_variable; }
|
void set_check_sys_variable(bool check_sys_variable) { check_sys_variable_ = check_sys_variable; }
|
||||||
@ -1990,7 +1993,12 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
transaction::ObTxDesc *tx_desc_;
|
transaction::ObTxDesc *tx_desc_;
|
||||||
transaction::ObTxExecResult tx_result_; // TODO: move to QueryCtx/ExecCtx
|
transaction::ObTxExecResult tx_result_; // TODO: move to QueryCtx/ExecCtx
|
||||||
share::SCN unused_read_snapshot_version_;//serialize compatibility preserved
|
// reserved read snapshot version for current or previous stmt in the txn. And
|
||||||
|
// it is used for multi-version garbage colloector to collect ative snapshot.
|
||||||
|
// While it may be empty for the txn with ac = 1 and remote execution whose
|
||||||
|
// snapshot version is generated from remote server(called by start_stmt). So
|
||||||
|
// use it only query is active and version is valid.
|
||||||
|
share::SCN reserved_read_snapshot_version_;
|
||||||
transaction::ObXATransID xid_;
|
transaction::ObXATransID xid_;
|
||||||
bool associated_xa_; // session joined distr-xa-trans by xa-start
|
bool associated_xa_; // session joined distr-xa-trans by xa-start
|
||||||
int64_t cached_tenant_config_version_;
|
int64_t cached_tenant_config_version_;
|
||||||
|
|||||||
@ -1347,46 +1347,91 @@ bool GetMinActiveSnapshotVersionFunctor::operator()(sql::ObSQLSessionMgr::Key ke
|
|||||||
share::SCN snapshot_version(share::SCN::max_scn());
|
share::SCN snapshot_version(share::SCN::max_scn());
|
||||||
|
|
||||||
if (sess_info->is_in_transaction()) {
|
if (sess_info->is_in_transaction()) {
|
||||||
|
share::SCN desc_snapshot;
|
||||||
transaction::ObTxDesc *tx_desc = nullptr;
|
transaction::ObTxDesc *tx_desc = nullptr;
|
||||||
|
share::SCN sess_snapshot = sess_info->get_reserved_snapshot_version();
|
||||||
if (OB_ISNULL(tx_desc = sess_info->get_tx_desc())) {
|
if (OB_ISNULL(tx_desc = sess_info->get_tx_desc())) {
|
||||||
MVCC_LOG(WARN, "tx desc is nullptr", KPC(sess_info));
|
ret = OB_ERR_UNEXPECTED;
|
||||||
|
MVCC_LOG(ERROR, "tx desc is nullptr", K(ret), KPC(sess_info));
|
||||||
|
} else if (FALSE_IT(desc_snapshot = tx_desc->get_snapshot_version())) {
|
||||||
} else if (transaction::ObTxIsolationLevel::SERIAL == tx_desc->get_isolation_level() ||
|
} else if (transaction::ObTxIsolationLevel::SERIAL == tx_desc->get_isolation_level() ||
|
||||||
transaction::ObTxIsolationLevel::RR == tx_desc->get_isolation_level()) {
|
transaction::ObTxIsolationLevel::RR == tx_desc->get_isolation_level()) {
|
||||||
// Case 1: RR/SI with tx desc exists, so we can get snapshot version from tx desc
|
// Case 1: RR/SI with tx desc exists, it means the snapshot is get from
|
||||||
share::SCN tmp_snapshot_version = tx_desc->get_snapshot_version();
|
// scheduler and must maintained in the session and tx desc
|
||||||
if (tmp_snapshot_version.is_valid()) {
|
if (desc_snapshot.is_valid()) {
|
||||||
snapshot_version = tmp_snapshot_version;
|
snapshot_version = desc_snapshot;
|
||||||
}
|
}
|
||||||
MVCC_LOG(DEBUG, "RR/SI txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
MVCC_LOG(DEBUG, "RR/SI txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
K(snapshot_version), K(min_active_snapshot_version_), K(desc_snapshot),
|
||||||
|
K(sess_snapshot));
|
||||||
} else if (transaction::ObTxIsolationLevel::RC == tx_desc->get_isolation_level()) {
|
} else if (transaction::ObTxIsolationLevel::RC == tx_desc->get_isolation_level()) {
|
||||||
// Case 2: RC with tx desc exists, while the snapshot version is not
|
// Case 2: RC with tx desc exists, it may exists that snapshot is get from
|
||||||
// maintained, so we use query start time instead
|
// the executor and not maintained in the session and tx desc. So we need
|
||||||
// TODO(handora.qc): use better snapshot version
|
// use session query start time carefully
|
||||||
if (sql::ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
|
if (sql::ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
|
||||||
snapshot_version.convert_from_ts(sess_info->get_cur_state_start_time());
|
if (desc_snapshot.is_valid()) {
|
||||||
|
snapshot_version = desc_snapshot;
|
||||||
|
} else if (sess_snapshot.is_valid()) {
|
||||||
|
snapshot_version = sess_snapshot;
|
||||||
|
} else {
|
||||||
|
// We gave a 5 minutes redundancy when get from session query start
|
||||||
|
// time under the case that local snapshot from tx_desc and session
|
||||||
|
// is unusable
|
||||||
|
snapshot_version.convert_from_ts(sess_info->get_cur_state_start_time()
|
||||||
|
- 5L * 1000L * 1000L * 60L);
|
||||||
|
MVCC_LOG(INFO, "RC txn with tx_desc while from session start time",
|
||||||
|
K(MTL_ID()), KPC(tx_desc), KPC(sess_info), K(snapshot_version),
|
||||||
|
K(min_active_snapshot_version_), K(sess_info->get_cur_state_start_time()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MVCC_LOG(DEBUG, "RC txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
MVCC_LOG(DEBUG, "RC txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
K(snapshot_version), K(min_active_snapshot_version_), K(desc_snapshot),
|
||||||
|
K(sess_snapshot));
|
||||||
} else {
|
} else {
|
||||||
MVCC_LOG(WARN, "unknown txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
MVCC_LOG(INFO, "unknown txn with tx_desc", K(MTL_ID()), KPC(tx_desc), KPC(sess_info),
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
K(snapshot_version), K(min_active_snapshot_version_));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
share::SCN sess_snapshot = sess_info->get_reserved_snapshot_version();
|
||||||
if (transaction::ObTxIsolationLevel::SERIAL == sess_info->get_tx_isolation() ||
|
if (transaction::ObTxIsolationLevel::SERIAL == sess_info->get_tx_isolation() ||
|
||||||
transaction::ObTxIsolationLevel::RR == sess_info->get_tx_isolation()) {
|
transaction::ObTxIsolationLevel::RR == sess_info->get_tx_isolation()) {
|
||||||
// Case 3: RR/SI with tx desc does not exist, it is not for the scheduler
|
// Case 3: RR/SI with tx desc does not exist or not in tx, it is not for
|
||||||
MVCC_LOG(DEBUG, "RR/SI txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
// the current running scheduler
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
|
||||||
} else if (transaction::ObTxIsolationLevel::RC == sess_info->get_tx_isolation()) {
|
|
||||||
// Case 4: RC with tx desc does not exist, while the snapshot version is not
|
|
||||||
// maintained, so we use query start time instead
|
|
||||||
// TODO(handora.qc): use better snapshot version
|
|
||||||
if (sql::ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
|
if (sql::ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
|
||||||
snapshot_version.convert_from_ts(sess_info->get_cur_state_start_time());
|
if (sess_snapshot.is_valid()) {
|
||||||
|
snapshot_version = sess_snapshot;
|
||||||
|
} else {
|
||||||
|
// We gave a 5 minutes redundancy when get from session query start
|
||||||
|
// time under the case that local snapshot from tx_desc and session
|
||||||
|
// is unusable
|
||||||
|
snapshot_version.convert_from_ts(sess_info->get_cur_state_start_time()
|
||||||
|
- 5L * 1000L * 1000L * 60L);
|
||||||
|
MVCC_LOG(INFO, "RR/SI txn with non tx_desc while from session start time",
|
||||||
|
K(MTL_ID()), KPC(sess_info), K(snapshot_version), K(sess_snapshot),
|
||||||
|
K(min_active_snapshot_version_), K(sess_info->get_cur_state_start_time()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MVCC_LOG(DEBUG, "RR/SI txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
||||||
|
K(snapshot_version), K(min_active_snapshot_version_), K(sess_snapshot));
|
||||||
|
} else if (transaction::ObTxIsolationLevel::RC == sess_info->get_tx_isolation()) {
|
||||||
|
// Case 4: RC with tx desc does not exist, and the snapshot version may not
|
||||||
|
// maintained, so we use query start time instead
|
||||||
|
if (sql::ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
|
||||||
|
if (sess_snapshot.is_valid()) {
|
||||||
|
snapshot_version = sess_snapshot;
|
||||||
|
} else {
|
||||||
|
// We gave a 5 minutes redundancy when get from session query start
|
||||||
|
// time under the case that local snapshot from tx_desc and session
|
||||||
|
// is unusable
|
||||||
|
snapshot_version.convert_from_ts(sess_info->get_cur_state_start_time()
|
||||||
|
- 5L * 1000L * 1000L * 60L);
|
||||||
|
MVCC_LOG(INFO, "RC txn with non tx_desc while from session start time",
|
||||||
|
K(MTL_ID()), KPC(sess_info), K(snapshot_version), K(sess_snapshot),
|
||||||
|
K(min_active_snapshot_version_), K(sess_info->get_cur_state_start_time()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MVCC_LOG(DEBUG, "RC txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
MVCC_LOG(DEBUG, "RC txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
K(snapshot_version), K(min_active_snapshot_version_), K(sess_snapshot));
|
||||||
} else {
|
} else {
|
||||||
MVCC_LOG(INFO, "unknown txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
MVCC_LOG(INFO, "unknown txn with non tx_desc", K(MTL_ID()), KPC(sess_info),
|
||||||
K(snapshot_version), K(min_active_snapshot_version_));
|
K(snapshot_version), K(min_active_snapshot_version_));
|
||||||
|
|||||||
Reference in New Issue
Block a user