[4.1] support distributed txn free route

This commit is contained in:
chinaxing
2023-01-28 16:07:17 +08:00
committed by ob-robot
parent 1cdf1dff1c
commit 30d0adec61
89 changed files with 3978 additions and 518 deletions

View File

@ -48,6 +48,12 @@
LOG_WARN("session has been killed", KR(ret), KPC(session)); \
}
#endif
#define CHECK_TX_FREE_ROUTE(session, ...) \
if (OB_SUCC(ret) && session->is_txn_free_route_temp()) { \
__VA_ARGS__; \
ret = OB_ERR_UNEXPECTED; \
TRANS_LOG(ERROR, "trans act on txn temporary node", KR(ret), K(session->get_tx_id()), KPC(session)); \
}
namespace oceanbase
{
@ -67,7 +73,7 @@ static int get_tx_service(ObBasicSessionInfo *session,
auto tx_tenant_id = session->get_tx_desc()->get_tenant_id();
if (effective_tenant_id != tx_tenant_id) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("effective_tenant_id not equals to tx_tenant_id", K(ret), K(effective_tenant_id), K(tx_tenant_id));
LOG_ERROR("effective_tenant_id not equals to tx_tenant_id", K(ret), K(effective_tenant_id), K(tx_tenant_id), KPC(session));
}
}
if (OB_SUCC(ret)) {
@ -131,11 +137,14 @@ int ObSqlTransControl::explicit_start_trans(ObExecContext &ctx, const bool read_
transaction::ObTransService *txs = NULL;
uint64_t tenant_id = 0;
ObTransID tx_id;
bool cleanup = true;
CK (OB_NOT_NULL(plan_ctx), OB_NOT_NULL(session));
CHECK_SESSION(session);
CHECK_TX_FREE_ROUTE(session, cleanup = false);
if (OB_SUCC(ret) && session->is_in_transaction()) {
ret = OB_ERR_UNEXPECTED;
cleanup = false;
LOG_ERROR("nested start transaction not allowed", KR(ret), K(ctx));
}
OX (tenant_id = session->get_effective_tenant_id());
@ -155,13 +164,12 @@ int ObSqlTransControl::explicit_start_trans(ObExecContext &ctx, const bool read_
OZ (txs->acquire_tx(session->get_tx_desc(), session->get_sessid()));
OZ (txs->start_tx(*session->get_tx_desc(), tx_param), tx_param);
OX (tx_id = session->get_tx_desc()->get_tx_id());
OX (session->set_explicit_start_trans(true));
if (OB_FAIL(ret) && OB_NOT_NULL(txs) && OB_NOT_NULL(session->get_tx_desc())) {
if (OB_FAIL(ret) && cleanup && OB_NOT_NULL(txs) && OB_NOT_NULL(session->get_tx_desc())) {
txs->release_tx(*session->get_tx_desc());
session->get_tx_desc() = NULL;
}
OX (session->get_raw_audit_record().trans_id_ = session->get_tx_id());
NG_TRACE_EXT(start_trans, OB_ID(ret), ret,
OB_ID(trans_id), tx_id.get_id(),
OB_ID(timeout), tx_param.timeout_us_,
@ -185,19 +193,14 @@ int ObSqlTransControl::implicit_end_trans(ObExecContext &exec_ctx,
#ifndef NDEBUG
LOG_INFO("implicit end trans", K(is_rollback), K(exec_ctx.get_execution_id()), KP(callback));
#endif
int64_t t_id = 0;
if (OB_ISNULL(GET_MY_SESSION(exec_ctx))) {
// do nothing
} else if (OB_ISNULL(GET_MY_SESSION(exec_ctx)->get_tx_desc())) {
// do nothing
} else {
t_id = GET_MY_SESSION(exec_ctx)->get_tx_desc()->tid().get_id();
}
ObSQLSessionInfo *session = GET_MY_SESSION(exec_ctx);
CK (OB_NOT_NULL(session));
int64_t tx_id = 0;
OX (tx_id = session->get_tx_id().get_id());
CHECK_TX_FREE_ROUTE(session);
FLTSpanGuard(end_transaction);
OZ(end_trans(exec_ctx, is_rollback, false, callback));
FLT_SET_TAG(trans_id, t_id);
FLT_SET_TAG(trans_id, tx_id);
return ret;
}
@ -215,7 +218,7 @@ int ObSqlTransControl::explicit_end_trans(ObExecContext &exec_ctx, const bool is
if (OB_SUCC(ret) && session->get_tx_desc()) {
txn_id = session->get_tx_desc()->tid();
}
CHECK_TX_FREE_ROUTE(session);
if (exec_ctx.is_end_trans_async()) {
CK (OB_NOT_NULL(callback = &session->get_end_trans_cb()));
}
@ -316,12 +319,22 @@ int ObSqlTransControl::kill_query_session(ObSQLSessionInfo &session,
return ret;
}
int ObSqlTransControl::kill_idle_timeout_tx(ObSQLSessionInfo *session)
{
int ret = OB_SUCCESS;
using namespace oceanbase::transaction;
if (!session->can_txn_free_route()) {
ret = kill_tx(session, OB_TRANS_IDLE_TIMEOUT);
}
return ret;
}
int ObSqlTransControl::kill_tx(ObSQLSessionInfo *session, int cause)
{
auto session_id = session->get_sessid();
LOG_INFO("begin to kill tx", K(cause), K(session_id), KPC(session));
int ret = OB_SUCCESS;
if (session->is_in_transaction()) {
if (session->is_in_transaction() && !session->is_txn_free_route_temp()) {
transaction::ObTxDesc *tx_desc = session->get_tx_desc();
auto tx_tenant_id = tx_desc->get_tenant_id();
const ObTransID tx_id = tx_desc->get_tx_id();
@ -494,7 +507,9 @@ int ObSqlTransControl::start_stmt(ObExecContext &exec_ctx)
if (OB_SUCC(ret) && !session->has_start_stmt()) {
OZ (session->set_start_stmt());
}
if (plan->is_contain_oracle_trx_level_temporary_table()) {
OX (tx_desc->set_with_temporary_table());
}
bool print_log = false;
#ifndef NDEBUG
print_log = true;
@ -648,6 +663,11 @@ int ObSqlTransControl::stmt_setup_savepoint_(ObSQLSessionInfo *session,
return ret;
}
#define CHECK_TXN_FREE_ROUTE_ALLOWED() \
if (OB_SUCC(ret) && !session->is_inner() && session->is_txn_free_route_temp()) { \
ret = OB_TRANS_FREE_ROUTE_NOT_SUPPORTED; \
LOG_WARN("current stmt is not allowed executed on txn tmp node", K(ret), KPC(session)); \
}
int ObSqlTransControl::create_savepoint(ObExecContext &exec_ctx,
const ObString &sp_name)
{
@ -656,6 +676,7 @@ int ObSqlTransControl::create_savepoint(ObExecContext &exec_ctx,
transaction::ObTransService *txs = NULL;
CK (OB_NOT_NULL(session));
CHECK_SESSION (session);
CHECK_TXN_FREE_ROUTE_ALLOWED();
OZ (get_tx_service(session, txs));
OZ (acquire_tx_if_need_(txs, *session));
OZ (txs->create_explicit_savepoint(*session->get_tx_desc(), sp_name), sp_name);
@ -673,6 +694,7 @@ int ObSqlTransControl::rollback_savepoint(ObExecContext &exec_ctx,
CK (OB_NOT_NULL(session), OB_NOT_NULL(plan_ctx));
CHECK_SESSION (session);
CHECK_TXN_FREE_ROUTE_ALLOWED();
OZ (get_tx_service(session, txs));
OZ (acquire_tx_if_need_(txs, *session));
OX (stmt_expire_ts = get_stmt_expire_ts(plan_ctx, *session));
@ -688,6 +710,7 @@ int ObSqlTransControl::release_savepoint(ObExecContext &exec_ctx,
transaction::ObTransService *txs = NULL;
CK (OB_NOT_NULL(session));
CHECK_SESSION (session);
CHECK_TXN_FREE_ROUTE_ALLOWED();
OZ (get_tx_service(session, txs), *session);
OZ (acquire_tx_if_need_(txs, *session));
OZ (txs->release_explicit_savepoint(*session->get_tx_desc(), sp_name), *session, sp_name);
@ -900,7 +923,6 @@ int ObSqlTransControl::reset_session_tx_state(ObBasicSessionInfo *session, bool
}
}
}
session->reset_first_need_txn_stmt_type();
session->get_trans_result().reset();
session->reset_tx_variable();
return ret;
@ -909,8 +931,11 @@ int ObSqlTransControl::reset_session_tx_state(ObBasicSessionInfo *session, bool
int ObSqlTransControl::reset_session_tx_state(ObSQLSessionInfo *session, bool reuse_tx_desc)
{
int temp_ret = OB_SUCCESS;
// cleanup temp tables created during txn progress
if (session->has_tx_level_temp_table()) {
// cleanup txn level temp tables if this is the txn start node
auto tx_desc = session->get_tx_desc();
if (OB_NOT_NULL(tx_desc)
&& tx_desc->with_temporary_table()
&& tx_desc->get_addr() == GCONF.self_addr_) {
temp_ret = session->drop_temp_tables(false);
if (OB_SUCCESS != temp_ret) {
LOG_WARN("trx level temporary table clean failed", KR(temp_ret));
@ -1040,7 +1065,76 @@ int ObSqlTransControl::check_ls_readable(const uint64_t tenant_id,
can_read = true;
}
}
return ret;
}
#define DELEGATE_TO_TXN(name) \
int ObSqlTransControl::update_txn_##name##_state(ObSQLSessionInfo &session, const char* buf, const int64_t len, int64_t &pos) \
{ \
int ret = OB_SUCCESS; \
transaction::ObTransService *txs = NULL; \
OZ (get_tx_service(&session, txs)); \
auto &tx_desc = session.get_tx_desc(); \
bool has_tx_desc = OB_NOT_NULL(tx_desc); \
transaction::ObTransID prev_tx_id; \
if (has_tx_desc) { prev_tx_id = session.get_tx_id(); } \
OZ (txs->txn_free_route__update_##name##_state(session.get_sessid(), tx_desc, session.get_txn_free_route_ctx(), buf, len, pos)); \
if (OB_SUCC(ret) && has_tx_desc && (OB_ISNULL(tx_desc) || tx_desc->get_tx_id() != prev_tx_id)) { \
session.reset_tx_variable(); \
} \
LOG_DEBUG("update-txn-state", K(ret), K(session), K(prev_tx_id), KPC(tx_desc)); \
return ret; \
} \
int ObSqlTransControl::serialize_txn_##name##_state(ObSQLSessionInfo &session, char* buf, const int64_t len, int64_t &pos) \
{ \
int ret = OB_SUCCESS; \
transaction::ObTransService *txs = NULL; \
OZ (get_tx_service(&session, txs)); \
OZ (txs->txn_free_route__serialize_##name##_state(session.get_sessid(), session.get_tx_desc(), session.get_txn_free_route_ctx(), buf, len, pos)); \
LOG_DEBUG("serialize-txn-state", K(session)); \
return ret; \
} \
int64_t ObSqlTransControl::get_txn_##name##_state_serialize_size(ObSQLSessionInfo &session) \
{ \
int ret = OB_SUCCESS; \
transaction::ObTransService *txs = NULL; \
OZ (get_tx_service(&session, txs)); \
if (OB_SUCC(ret)) { \
return txs->txn_free_route__get_##name##_state_serialize_size(session.get_tx_desc(), session.get_txn_free_route_ctx()); \
} \
LOG_DEBUG("get-serialize-size-txn-state", K(session)); \
return ret; \
}
DELEGATE_TO_TXN(static);
DELEGATE_TO_TXN(dynamic);
DELEGATE_TO_TXN(parts);
DELEGATE_TO_TXN(extra);
#undef DELEGATE_TO_TXN
int ObSqlTransControl::calc_txn_free_route(ObSQLSessionInfo &session, transaction::ObTxnFreeRouteCtx &txn_free_route_ctx)
{
int ret = OB_SUCCESS;
transaction::ObTransService *txs = NULL;
MTL_SWITCH(session.get_effective_tenant_id()) {
OZ (get_tx_service(&session, txs));
OZ (txs->calc_txn_free_route(session.get_tx_desc(), txn_free_route_ctx));
}
return ret;
}
int ObSqlTransControl::check_free_route_tx_alive(ObSQLSessionInfo &session, transaction::ObTxnFreeRouteCtx &txn_free_route_ctx)
{
int ret = OB_SUCCESS;
auto tx = session.get_tx_desc();
if (OB_NOT_NULL(tx)) {
MTL_SWITCH(tx->get_tenant_id()) {
transaction::ObTransService *txs = MTL(transaction::ObTransService*);
CK (OB_NOT_NULL(txs));
OZ (txs->tx_free_route_check_alive(txn_free_route_ctx, *tx, session.get_sessid()));
}
}
return ret;
}