diff --git a/src/sql/engine/expr/ob_expr_lock_func.cpp b/src/sql/engine/expr/ob_expr_lock_func.cpp index b8da22134..132c412d6 100644 --- a/src/sql/engine/expr/ob_expr_lock_func.cpp +++ b/src/sql/engine/expr/ob_expr_lock_func.cpp @@ -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; diff --git a/src/storage/tablelock/ob_lock_func_executor.cpp b/src/storage/tablelock/ob_lock_func_executor.cpp index 06fd54e1d..4720294e2 100644 --- a/src/storage/tablelock/ob_lock_func_executor.cpp +++ b/src/storage/tablelock/ob_lock_func_executor.cpp @@ -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; } diff --git a/src/storage/tablelock/ob_lock_func_executor.h b/src/storage/tablelock/ob_lock_func_executor.h index 22222f64f..b3178323e 100644 --- a/src/storage/tablelock/ob_lock_func_executor.h +++ b/src/storage/tablelock/ob_lock_func_executor.h @@ -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