2
* Copyright (c) 2021 OceanBase
3
* OceanBase CE is licensed under Mulan PubL v2.
4
* You can use this software according to the terms and conditions of the Mulan PubL v2.
5
* You may obtain a copy of Mulan PubL v2 at:
6
* http://license.coscl.org.cn/MulanPubL-2.0
7
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
* See the Mulan PubL v2 for more details.
13
#define USING_LOG_PREFIX SERVER
15
#include "obmp_disconnect.h"
17
#include "lib/stat/ob_session_stat.h"
18
#include "rpc/ob_request.h"
19
#include "observer/ob_server_struct.h"
20
#include "sql/session/ob_sql_session_mgr.h"
21
#include "sql/ob_sql_trans_control.h"
23
using namespace oceanbase::observer;
24
using namespace oceanbase::common;
26
ObMPDisconnect::ObMPDisconnect(const sql::ObFreeSessionCtx &ctx)
31
ObMPDisconnect::~ObMPDisconnect()
36
int ObMPDisconnect::kill_unfinished_session(uint32_t sessid)
39
sql::ObSQLSessionInfo *session = NULL;
40
sql::ObSessionGetterGuard guard(*GCTX.session_mgr_, sessid);
41
if (OB_FAIL(guard.get_session(session))) {
42
LOG_WARN("get session fail", K(ret));
43
} else if (OB_ISNULL(session)) {
44
ret = OB_ERR_UNEXPECTED;
45
LOG_ERROR("fail to get session info", K(session), K(sessid), K(ret));
48
* 在Disconnect的上下文中,两种可能:
49
* (1) 长SQL先执行,并且正在执行,那么它已经能够检测到IS_KILLED标记
50
* 此时disconnect_session会等待长SQL执行退出后才结束session中的事务
51
* (2) disconnect_session先执行,它会结束事务并返回,然后执行后面的free_session
52
* (free_session 并不是释放 session 内存,只是一个逻辑删除的动作)。
53
* 当长SQL拿到query_lock锁,它会立即检测IS_KILLED状态,检测到后立即退出处理流程。
54
* 最终引用计数减为0,session被物理回收。
56
if (OB_FAIL(GCTX.session_mgr_->disconnect_session(*session))) {
57
LOG_WARN("fail to disconnect session", K(session), K(sessid), K(ret));
63
int ObMPDisconnect::run()
66
bool is_need_clear = false;
67
if (ctx_.sessid_ != 0) {
68
if (OB_ISNULL(GCTX.session_mgr_)) {
69
ret = OB_INVALID_ARGUMENT;
70
LOG_WARN("invalid session mgr", K(GCTX.session_mgr_), K(ret));
73
conn.sessid_ = ctx_.sessid_;
74
conn.is_need_clear_sessid_ = true;
76
(void) kill_unfinished_session(ctx_.sessid_); // ignore ret
77
if (OB_FAIL(GCTX.session_mgr_->free_session(ctx_))) {
78
LOG_WARN("free session fail", K(ctx_));
80
common::ObTenantStatEstGuard guard(ctx_.tenant_id_);
81
EVENT_INC(SQL_USER_LOGOUTS_CUMULATIVE);
82
LOG_INFO("free session successfully", "sessid", ctx_.sessid_);
83
if (OB_UNLIKELY(OB_FAIL(sql::ObSQLSessionMgr::is_need_clear_sessid(&conn, is_need_clear)))) {
84
LOG_ERROR("fail to judge need clear", K(ret), "sessid", conn.sessid_, "server_id", GCTX.server_id_);
85
} else if (is_need_clear) {
86
if (OB_FAIL(GCTX.session_mgr_->mark_sessid_unused(conn.sessid_))) {
87
LOG_WARN("mark session id unused failed", K(ret), "sessid", conn.sessid_);
89
LOG_INFO("mark session id unused", "sessid", conn.sessid_);