[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; int ret = OB_SUCCESS;
ObDatum *lock_name = NULL; ObDatum *lock_name = NULL;
int64_t release_cnt = ObLockFuncExecutor::INVALID_RELEASE_CNT;
if (!proxy_is_support(ctx.exec_ctx_)) { if (!proxy_is_support(ctx.exec_ctx_)) {
ret = OB_NOT_SUPPORTED; ret = OB_NOT_SUPPORTED;
LOG_WARN("obproxy is not support mysql lock function", K(ret)); 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; ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument, lock name should not be null", K(ret)); LOG_WARN("invalid argument, lock name should not be null", K(ret));
} else if (OB_FAIL(executor.execute(ctx.exec_ctx_, } 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)); LOG_WARN("release lock failed", K(ret), K(lock_name_str));
} }
} }
// 1 release success
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
result.set_int(1); if (release_cnt < 0) {
} else if (OB_EMPTY_RESULT == ret) { result.set_null();
// 2 there is no lock } else {
ret = OB_SUCCESS; result.set_int(release_cnt);
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);
} else { } else {
// 4 some thing error.
result.set_null(); result.set_null();
} }
@ -483,11 +480,14 @@ int ObExprReleaseAllLocks::release_all_locks(const ObExpr &expr,
} else { } else {
ret = executor.execute(ctx.exec_ctx_, release_cnt); ret = executor.execute(ctx.exec_ctx_, release_cnt);
} }
// 1. release all locks success.
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
result.set_int(release_cnt); if (release_cnt < 0) {
result.set_null();
} else {
result.set_int(release_cnt);
}
} else { } else {
// 2. some thing error.
result.set_null(); result.set_null();
} }
return ret; return ret;

View File

@ -977,7 +977,8 @@ int ObGetLockExecutor::get_sql_port_(ObLockFuncContext &ctx,
} }
int ObReleaseLockExecutor::execute(ObExecContext &ctx, int ObReleaseLockExecutor::execute(ObExecContext &ctx,
const ObString &lock_name) const ObString &lock_name,
int64_t &release_cnt)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS;
@ -989,6 +990,8 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
bool lock_id_existed = false; bool lock_id_existed = false;
ObLockID tmp_lock_id; ObLockID tmp_lock_id;
release_cnt = INVALID_RELEASE_CNT; // means not release successfully
OZ (ObLockFuncContext::valid_execute_context(ctx)); OZ (ObLockFuncContext::valid_execute_context(ctx));
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
SMART_VAR(ObLockFuncContext, stack_ctx) { SMART_VAR(ObLockFuncContext, stack_ctx) {
@ -1001,8 +1004,8 @@ int ObReleaseLockExecutor::execute(ObExecContext &ctx,
ObTxParam tx_param; ObTxParam tx_param;
ObUnLockObjsRequest arg; ObUnLockObjsRequest arg;
ObTableLockOwnerID lock_owner; ObTableLockOwnerID lock_owner;
// 1. check client_session_id is valid // 1. get lock id from inner table
// 2. get lock id from inner table // 2. check client_session_id is valid
// 3. unlock obj // 3. unlock obj
// 4. modify inner table // 4. modify inner table
// 4.1 lock table: dec cnt if the cnt is greater than 1, else remove the record. // 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. // 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 // 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. // 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()) { if (ctx.get_my_session()->is_obproxy_mode()) {
OZ (check_client_ssid_(stack_ctx, client_session_id, client_session_create_ts)); 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 (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 (ObInnerConnectionLockUtil::build_tx_param(session, tx_param));
OZ (tmp_lock_id.set(ObLockOBJType::OBJ_TYPE_MYSQL_LOCK_FUNC, lock_id)); 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) { if (OB_SUCC(ret) && need_remove_from_lock_table) {
OZ (unlock_obj_(tx_desc, tx_param, arg)); OZ (unlock_obj_(tx_desc, tx_param, arg));
OZ (remove_session_record_(stack_ctx, client_session_id, client_session_create_ts)); OZ (remove_session_record_(stack_ctx, client_session_id, client_session_create_ts));
OX (release_cnt = 1);
} else if (OB_EMPTY_RESULT == ret) { } else if (OB_EMPTY_RESULT == ret) {
if (OB_TMP_FAIL(check_lock_exist_(stack_ctx, lock_id, lock_id_existed))) { 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)); LOG_WARN("check lock_id existed failed", K(tmp_ret), K(lock_id));
} else if (lock_id_existed) { } 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; return ret;
} }
@ -1111,6 +1128,7 @@ int ObReleaseAllLockExecutor::execute_(ObExecContext &ctx,
int tmp_ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS;
bool is_rollback = false; bool is_rollback = false;
ObTableLockOwnerID owner_id; ObTableLockOwnerID owner_id;
release_cnt = INVALID_RELEASE_CNT; // means not release successfully
OZ (ObLockFuncContext::valid_execute_context(ctx)); OZ (ObLockFuncContext::valid_execute_context(ctx));
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
SMART_VAR(ObLockFuncContext, stack_ctx) { SMART_VAR(ObLockFuncContext, stack_ctx) {
@ -1121,6 +1139,9 @@ int ObReleaseAllLockExecutor::execute_(ObExecContext &ctx,
ObTxParam tx_param; ObTxParam tx_param;
if (ctx.get_my_session()->is_obproxy_mode()) { if (ctx.get_my_session()->is_obproxy_mode()) {
OZ (check_client_ssid_(stack_ctx, client_session_id, client_session_create_ts)); 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 (ObInnerConnectionLockUtil::build_tx_param(session, tx_param));
OZ (owner_id.convert_from_client_sessid(client_session_id, client_session_create_ts)); 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; return ret;
} }

View File

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