数据库会话数量过多,定期清理inactive会话

本文探讨了Oracle数据库中大量非活跃会话的影响及其处理方法,包括内存和CPU资源消耗等问题,并提供了解决方案,如定期清理非活跃会话、利用MAX_IDLE_TIME参数自动终止会话等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.1现象
存在一套11.2.0.4 RAC 2节点,数据库存在5000个会话数量,其中active正在执行的会话500个,其余均为非活跃会话。

大量inactive会话过多给Oracle数据库带来什么样的影响?

 [活跃说明数据库存在大量并发,正常情况下说明是业务负载这块只能拆库,常规无法优化套路】
  1. 内存消耗,每个会话对应数据库来说都是一个pga process 需要单独分配一块内存区域,并且其中会话保留的游标越多,越消耗内存;

  2. cpu资源消耗,每个会话对应操作系统来说都是一个Oracle用户进程,虽然大量属于inactive 但是对于操作系统来说还是一个进程运行;

1.2相关参数
复制代码
SESSIONS
Default value Derived: (1.5 * PROCESSES) + 22
Range of values 1 to 216 (which is 1 to 65536)
SESSIONS specifies the maximum number of sessions that can be created in the system. Because every login requires a session, this parameter effectively determines
the maximum number of concurrent users in the system. You should always set this parameter explicitly to a value equivalent to your estimate of the maximum number of concurrent users,
plus the number of background processes, plus approximately 10% for recursive sessions.

PROCESSES
Default value 100
Range of values 6 to operating system dependent
PROCESSES specifies the maximum number of operating system user processes that can simultaneously connect to Oracle. Its value should allow for all background processes such as locks,
job queue processes, and parallel execution processes.

vi /etc/security/limits.conf

oracle soft nproc 32
oracle hard nproc 64
#ulimit -a
复制代码

1.3 方法论
复制代码
状态
1.活跃会话基本上无法处理,Oracle数据库拆分[极端情况例如:会话挤压等异常情况,处理数据库异常后,活跃会话趋于平稳】;
2.非活跃会话可以定期清理

参考文档
https://www.anbob.com/archives/5837.html

非活跃会话方法论:
A:dead session
Dead connection detection(DCD)是Oracle网络功能,主要用于客户端关闭其系统电源或客户端计算机意外崩溃而又无法正常关闭Oracle数据库连接的环境。
如果客户端计算机因正确断开会话而突然崩溃,则这些会话锁定的资源将继续被锁定,从而导致环境性能问题。由于这种情况可以在任何环境中发生,因此Oracle网络服务提供了DCD的功能,可以在早期检测到这种情况,从而可以快速恢复锁定的资源。
为了解决这种情况并检测死连接,Oracle在网络会话(12c中的tcp)层引入了一个新概念。服务器进程将SQL * Net Probe数据包发送到客户端,以检查在sqlnet.expire_time【单位:分钟】参数指定的每个固定时间间隔内连接是否仍然可用。
如果通过探测数据包的通信失败,则会返回错误,导致服务器进程退出。
SQLNET.EXPIRE_TIME = 10

B:idel session
1.WAS等中间件或程序软件,存在会话一定时间不工作自动断开设置;
2.MAX_IDLE_TIME指定会话可以空闲的最大分钟数。 此后会话将自动终止。12.2 引入的新参数。这参数是整个db或CDB级,不可以alter session. 单位分钟,超过idle上限时间后会收到 ORA-03113错误。
3.编写plsql脚本,定期执行[如下详细说明]

C:idle blocker session
1.目前常规基本上都是DBA人为参与处理;
2.如果一个idle session阻塞了其他会话,在19c 20c中可以使用参数max_idle_blocker_time 自动终止blocker, 当会话持有其他会话所需的资源时,该会话被视为阻塞会话.
1)如 该会话持有另一个会话所需的锁。
2)该会话是并行操作,并且其使用者组,PDB或数据库已达到其最大并行服务器限制或已排队的并行操作。
3)会话的PDB或数据库实例即将达到其SESSIONS或PROCESSES限制。
此参数与MAX_IDLE_TIME参数的不同之处在于,MAX_IDLE_TIME适用于所有会话(阻塞和非阻塞),而MAX_IDLE_BLOCKING_TIME仅适用于阻塞会话。 因此,为了使MAX_IDLE_BLOCKING_TIME有效,其限制必须小于MAX_IDLE_TIME限制。
复制代码
1.4 模拟人工处理
复制代码
操作系统并发20进行登录,使用1000并发测试主机hang
#!/bin/bash
i=1
while (($i<=20))
do
sqlplus -S scott/tiger &
let “i++”
echo $1
done

测试环境process 400达到上限报错

ERROR:
ORA-00020: maximum number of processes (400) exceeded
Thu Oct 22 02:24:15 2020
ORA-00020: maximum number of processes (400) exceeded
ORA-20 errors will not be written to the alert log for
the next minute. Please look at trace files to see all
the ORA-20 errors.
Process m000 submission failed with error = 20
Process m000 submission failed with error = 20
Process m000 submission failed with error = 20
Process m000 submission failed with error = 20
Thu Oct 22 02:24:18 2020

DB 什么视图记录历史登录情况达到上限值???
SQL> SELECT * FROM GV$RESOURCE_LIMIT WHERE RESOURCE_NAME=‘sessions’ or RESOURCE_NAME=‘processes’;

手工方法输出KILL语句

SELECT STATUS,COUNT(*) FROM GVSESSIONGROUPBYSTATUS;selectusername,round(LASTCALLET/3600)as"HH24",count(∗)fromgvSESSION GROUP BY STATUS; select username,round(LAST_CALL_ET/3600) as "HH24",count(*) from gvSESSIONGROUPBYSTATUS;selectusername,round(LASTCALLET/3600)as"HH24",count()fromgvsession where status=‘INACTIVE’
group by username,round(LAST_CALL_ET/3600) order by 2,3,1;
select ‘ALTER SYSTEM KILL session ‘’’||sid||’,’||serial#||’’’ IMMEDIATE;’ AS “KILL_SQL” from vKaTeX parse error: Expected 'EOF', got '#' at position 136: …id||','||serial#̲||''' IMMEDIATE…session where status=‘INACTIVE’
AND LAST_CALL_ET>36000 AND USERNAME=‘CB’;

plsql执行kill inactive session

SET SERVEROUTPUT ON
DECLARE
P_SID NUMBER;
P_SERIAL NUMBER;
P_STATUS VARCHAR2(32);
KILL_SQLTEXT VARCHAR2(4000);
CURSOR CUR_APP_ID IS
SELECT
SID, SERIAL#
FROM
VSESSIONWHERESTATUS=′INACTIVE′ANDUSERNAMEIN(′SCOTT′)ANDSTATUS=′INACTIVE′ANDLASTCALLET>6;BEGINOPENCURAPPID;LOOPFETCHCURAPPIDINTOPSID,PSERIAL;EXITWHENCURAPPIDSELECTSTATUSINTOPSTATUSFROMVSESSION WHERE STATUS = 'INACTIVE' AND USERNAME IN('SCOTT') AND STATUS = 'INACTIVE' AND LAST_CALL_ET >6 ; BEGIN OPEN CUR_APP_ID; LOOP FETCH CUR_APP_ID INTO P_SID,P_SERIAL; EXIT WHEN CUR_APP_ID%NOTFOUND; SELECT STATUS INTO P_STATUS FROM VSESSIONWHERESTATUS=INACTIVEANDUSERNAMEIN(SCOTT)ANDSTATUS=INACTIVEANDLASTCALLET>6;BEGINOPENCURAPPID;LOOPFETCHCURAPPIDINTOPSID,PSERIAL;EXITWHENCURAPPIDSELECTSTATUSINTOPSTATUSFROMVSESSION
WHERE
SID = P_SID AND SERIAL# = P_SERIAL AND USERNAME IN(‘SCOTT’) AND STATUS = ‘INACTIVE’ AND LAST_CALL_ET >6 ;
IF P_STATUS = ‘INACTIVE’ THEN
KILL_SQLTEXT := ‘ALTER SYSTEM KILL SESSION ‘||CHR(39)||P_SID || ‘,’ || P_SERIAL ||CHR(39)||’ IMMEDIATE’;
EXECUTE IMMEDIATE KILL_SQLTEXT;
DBMS_OUTPUT.PUT_LINE(KILL_SQLTEXT);
END IF;
END LOOP;
CLOSE CUR_APP_ID;
END;
/
复制代码

1.5 配置定时任务
复制代码
!对于RAC 2节点,需要每个节点都配置这个脚本,建议时间错开一定时间,例如30分钟。 通过实际执行发现kill 1300 inactive session话费时间3分钟左右。
[oracle@test script]$ chmod +x kill_inactive_session.sh
[oracle@test script]$ cat kill_inactive_session.sh
#!/bin/bash
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1/
export ORACLE_SID=tt
export PATH=PATH:PATH:PATH:HOME/bin:$ORACLE_HOME/bin
sqlplus / as sysdba <<EOF
spool /home/oracle/script/kill_session.log
select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss’) as “date” from dual;
SET SERVEROUTPUT ON
DECLARE
P_SID NUMBER;
P_SERIAL NUMBER;
P_STATUS VARCHAR2(32);
KILL_SQLTEXT VARCHAR2(4000);
CURSOR CUR_APP_ID IS
SELECT
SID, SERIAL#
FROM
V$SESSION
WHERE STATUS = ‘INACTIVE’ AND USERNAME IN(‘SCOTT’) AND STATUS = ‘INACTIVE’ AND LAST_CALL_ET >6 ;
BEGIN
OPEN CUR_APP_ID;
LOOP
FETCH CUR_APP_ID INTO P_SID,P_SERIAL;
EXIT WHEN CUR_APP_ID%NOTFOUND;
SELECT
STATUS
INTO P_STATUS
FROM
V$SESSION
WHERE
SID = P_SID AND SERIAL# = P_SERIAL AND USERNAME IN(‘SCOTT’) AND STATUS = ‘INACTIVE’ AND LAST_CALL_ET >6 ;
IF P_STATUS = ‘INACTIVE’ THEN
KILL_SQLTEXT := ‘ALTER SYSTEM KILL SESSION ‘||CHR(39)||P_SID || ‘,’ || P_SERIAL ||CHR(39)||’ IMMEDIATE’;
EXECUTE IMMEDIATE KILL_SQLTEXT;
DBMS_OUTPUT.PUT_LINE(KILL_SQLTEXT);
END IF;
END LOOP;
CLOSE CUR_APP_ID;
END;
/
exit;
EOF

[oracle@test script]$ crontab -l
01 07,21 * * * sh /home/oracle/script/kill_inactive_session.sh &

tail -200f //var/log/cron

Oct 22 07:00:01 test crond[4834]: (oracle) CMD (sh /home/oracle/script/kill_inactive_session.sh &)

<think>好的,我现在需要回答用户关于达梦数据库如何查看会话空闲时间的问题。首先,我得确认用户的需求是了解如何查询当前会话的空闲状态,可能用于监控或优化数据库性能。 首先,我应该回忆达梦数据库的系统视图,因为通常这类信息会存储在系统视图中。达梦常用的系统视图包括V$SESSIONS、V$SESSION_LONGOPS等。V$SESSIONS视图通常包含会话的详细信息,比如登录时间、状态等。是否有字段直接表示空闲时间呢?可能需要计算,比如用当前时间减去最后一次操作的时间。 接下来,用户可能需要具体的SQL语句。我需要检查V$SESSIONS中的字段,例如STATUS字段可能显示会话是ACTIVE还是INACTIVE。另外,是否有LAST_RECV_TIME或类似的字段记录最后一次接收请求的时间?如果有,可以用SYSDATE减去这个时间得到空闲时长。 然后,需要考虑权限问题。普通用户可能需要特定权限才能查询这些视图,比如SELECT_CATALOG_ROLE或者被授予直接查询V$SESSION的权限。需要提醒用户注意权限。 此外,是否需要考虑达梦的版本差异?不同版本可能字段名称不同,比如较新的版本可能添加了更多监控指标。如果不确定,建议用户查阅对应版本的官方文档。 可能的SQL语句结构是: SELECT SESS_ID, STATUS, LAST_RECV_TIME, SYSDATE - LAST_RECV_TIME AS IDLE_TIME FROM V$SESSIONS WHERE ...; 另外,是否有内置的存储过程或函数可以获取空闲时间?比如达梦的某些管理包。但可能更直接的方法是使用系统视图。 需要验证这个SQL是否正确。假设LAST_RECV_TIME存在,并且SYSDATE是当前时间,那么计算差值可能得到分钟或秒级别的空闲时间。但要注意时间格式的转换,可能需要使用DATEDIFF函数,例如DATEDIFF(minute, LAST_RECV_TIME, SYSDATE) AS IDLE_MINUTES。 可能还需要处理NULL值的情况,如果LAST_RECV_TIME为空,可能表示会话刚创建还未有操作。 最后,要确保回答结构清晰,分步骤说明,并提醒用户权限和版本差异的问题。如果有不确定的地方,建议参考官方文档或联系技术支持。</think>在达梦数据库中查看会话空闲时间,可通过以下步骤实现: --- ### 步骤1:使用系统视图 `V$SESSIONS` 达梦数据库会话信息存储在系统视图 `V$SESSIONS` 中,需重点关注以下字段: - **`SESS_ID`**:会话ID - **`STATUS`**:会话状态(`ACTIVE`表示活跃,`INACTIVE`表示空闲) - **`LAST_RECV_TIME`**:最后一次接收到请求的时间戳 - **`CREATE_TIME`**:会话创建时间 --- ### 步骤2:编写SQL查询空闲时间 通过计算 **当前时间** 与 **`LAST_RECV_TIME`** 的差值,可得到空闲时长: ```sql SELECT SESS_ID, STATUS, LAST_RECV_TIME, DATEDIFF(SECOND, LAST_RECV_TIME, SYSDATE) AS IDLE_SECONDS -- 计算空闲秒数 FROM V$SESSIONS WHERE STATUS = 'INACTIVE'; -- 筛选空闲会话 ``` --- ### 步骤3:关键字段说明 1. **`STATUS`** - `ACTIVE`:会话正在执行SQL或事务。 - `INACTIVE`:会话处于空闲状态。 2. **`IDLE_SECONDS`** - 数值越大,表示会话空闲时间越长(单位:秒)。 --- ### 补充说明 - **权限要求**:需具有 `SELECT` 权限访问 `V$SESSIONS` 视图。 - **版本差异**:不同达梦版本字段可能略有不同,建议参考对应版本的《DM8系统管理员手册》。 - **监控工具**:可通过达梦管理工具(如管理监控客户端)图形化查看会话状态。 --- 通过上述方法,可有效监控会话空闲情况,辅助进行资源优化或会话清理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值