[TABLELOCK] Fix bug about calling release_all_locks when session doesn't hold any locks

This commit is contained in:
YangEfei 2024-05-30 09:04:30 +00:00 committed by ob-robot
parent e4bf916318
commit e76485f957
3 changed files with 52 additions and 21 deletions

View File

@ -408,6 +408,8 @@ int ObExprReleaseLock::release_lock(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
int ret = OB_SUCCESS;
ObDatum *lock_name = NULL;
int64_t release_cnt = ObLockFuncExecutor::INVALID_RELEASE_CNT;
if (!proxy_is_support(ctx.exec_ctx_)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("obproxy is not support mysql lock function", K(ret));
@ -425,24 +427,19 @@ int ObExprReleaseLock::release_lock(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument, lock name should not be null", K(ret));
} else if (OB_FAIL(executor.execute(ctx.exec_ctx_,
lock_name_str))) {
lock_name_str,
release_cnt))) {
LOG_WARN("release lock failed", K(ret), K(lock_name_str));
}
}
// 1 release success
if (OB_SUCC(ret)) {
result.set_int(1);
} else if (OB_EMPTY_RESULT == ret) {
// 2 there is no lock
ret = OB_SUCCESS;
result.set_null();
} else if (OB_OBJ_LOCK_NOT_EXIST == ret) {
// 3 the lock is not belong to current client session
ret = OB_SUCCESS;
result.set_int(0);
if (release_cnt < 0) {
result.set_null();
} else {
result.set_int(release_cnt);
}
} else {
// 4 some thing error.
result.set_null();
}
@ -483,11 +480,14 @@ int ObExprReleaseAllLocks::release_all_locks(const ObExpr &expr,
} else {
ret = executor.execute(ctx.exec_ctx_, release_cnt);
}
// 1. release all locks success.
if (OB_SUCC(ret)) {
result.set_int(release_cnt);
if (release_cnt < 0) {
result.set_null();
} else {
result.set_int(release_cnt);
}
} else {
// 2. some thing error.
result.set_null();
}
return ret;

View File

@ -977,7 +977,8 @@ int ObGetLockExecutor::get_sql_port_(ObLockFuncContext &ctx,
}
int ObReleaseLockExecutor::execute(ObExecContext &ctx,
const ObString &lock_name)
const ObString &lock_name,
int64_t &release_cnt)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
@ -989,6 +990,8 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
bool lock_id_existed = false;
ObLockID tmp_lock_id;
release_cnt = INVALID_RELEASE_CNT; // means not release successfully
OZ (ObLockFuncContext::valid_execute_context(ctx));
if (OB_SUCC(ret)) {
SMART_VAR(ObLockFuncContext, stack_ctx) {
@ -1001,8 +1004,8 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
ObTxParam tx_param;
ObUnLockObjsRequest arg;
ObTableLockOwnerID lock_owner;
// 1. check client_session_id is valid
// 2. get lock id from inner table
// 1. get lock id from inner table
// 2. check client_session_id is valid
// 3. unlock obj
// 4. modify inner table
// 4.1 lock table: dec cnt if the cnt is greater than 1, else remove the record.
@ -1011,11 +1014,17 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
// lock id, remove the record at lock name-id table.
// 4.3 session table: check the lock table if there is no lock of the same
// client session, remove the record of the same client session id.
OZ (query_lock_id_(lock_name, lock_id));
if (OB_EMPTY_RESULT == ret) {
release_cnt = LOCK_NOT_EXIST_RELEASE_CNT;
}
if (ctx.get_my_session()->is_obproxy_mode()) {
OZ (check_client_ssid_(stack_ctx, client_session_id, client_session_create_ts));
if (OB_EMPTY_RESULT == ret) {
release_cnt = LOCK_NOT_OWN_RELEASE_CNT;
}
}
OZ (lock_owner.convert_from_client_sessid(client_session_id, client_session_create_ts));
OZ (query_lock_id_(lock_name, lock_id));
OZ (ObInnerConnectionLockUtil::build_tx_param(session, tx_param));
OZ (tmp_lock_id.set(ObLockOBJType::OBJ_TYPE_MYSQL_LOCK_FUNC, lock_id));
@ -1031,11 +1040,14 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
if (OB_SUCC(ret) && need_remove_from_lock_table) {
OZ (unlock_obj_(tx_desc, tx_param, arg));
OZ (remove_session_record_(stack_ctx, client_session_id, client_session_create_ts));
OX (release_cnt = 1);
} else if (OB_EMPTY_RESULT == ret) {
if (OB_TMP_FAIL(check_lock_exist_(stack_ctx, lock_id, lock_id_existed))) {
LOG_WARN("check lock_id existed failed", K(tmp_ret), K(lock_id));
} else if (lock_id_existed) {
ret = OB_OBJ_LOCK_NOT_EXIST; // when lock is hold by other session, return 0 as result
release_cnt = LOCK_NOT_OWN_RELEASE_CNT;
} else {
release_cnt = LOCK_NOT_EXIST_RELEASE_CNT;
}
}
}
@ -1046,6 +1058,11 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
}
}
}
// if release_cnt is valid, means we have tried to release,
// and have not encountered any failures before
if (INVALID_RELEASE_CNT != release_cnt) {
ret = OB_SUCCESS;
}
return ret;
}
@ -1111,6 +1128,7 @@ int ObReleaseAllLockExecutor::execute_(ObExecContext &ctx,
int tmp_ret = OB_SUCCESS;
bool is_rollback = false;
ObTableLockOwnerID owner_id;
release_cnt = INVALID_RELEASE_CNT; // means not release successfully
OZ (ObLockFuncContext::valid_execute_context(ctx));
if (OB_SUCC(ret)) {
SMART_VAR(ObLockFuncContext, stack_ctx) {
@ -1121,6 +1139,9 @@ int ObReleaseAllLockExecutor::execute_(ObExecContext &ctx,
ObTxParam tx_param;
if (ctx.get_my_session()->is_obproxy_mode()) {
OZ (check_client_ssid_(stack_ctx, client_session_id, client_session_create_ts));
if (OB_EMPTY_RESULT == ret) {
release_cnt = LOCK_NOT_OWN_RELEASE_CNT;
}
}
OZ (ObInnerConnectionLockUtil::build_tx_param(session, tx_param));
OZ (owner_id.convert_from_client_sessid(client_session_id, client_session_create_ts));
@ -1138,6 +1159,11 @@ int ObReleaseAllLockExecutor::execute_(ObExecContext &ctx,
}
}
}
// if release_cnt is valid, means we have tried to release,
// and have not encountered any failures before
if (INVALID_RELEASE_CNT != release_cnt) {
ret = OB_SUCCESS;
}
return ret;
}

View File

@ -126,6 +126,10 @@ public:
static constexpr int64_t MAX_LOCK_HANDLE_ID = 1999999999;
static constexpr int64_t DEFAULT_EXPIRATION_US = 60 * 1000 * 1000L; // 1min
static constexpr int64_t INVALID_RELEASE_CNT = -2;
static constexpr int64_t LOCK_NOT_EXIST_RELEASE_CNT = -1;
static constexpr int64_t LOCK_NOT_OWN_RELEASE_CNT = 0;
public:
int check_lock_exist_(const uint64_t &lock_id);
int check_lock_exist_(ObLockFuncContext &ctx,
@ -216,7 +220,8 @@ class ObReleaseLockExecutor : public ObLockFuncExecutor
{
public:
int execute(sql::ObExecContext &ctx,
const ObString &lock_name);
const ObString &lock_name,
int64_t &release_cnt);
};
class ObReleaseAllLockExecutor : public ObLockFuncExecutor