本帖最后由 bfc99 于 2015-9-18 11:10 编辑
yixiuquan 发表于 2015-9-18 09:34
SQL> select USERNAME,status,count(*) from v$session group by USERNAME,status order by 3;
USERNAME ...我觉得你的理解上可能有错误。以下是我对这个问题的认识和理解(我没有实际处理过类似的问题),供参考:
1、什么是SNIPED会话?
当一个会话是INACTIVE的,且INACTIVE的时长超过了某个限制,比如PROFILE中指定的IDLE_TIME时,这个会话的状态就会从INACTIVE变为SINPED。
以你的例子来说,就是当一个非活动会话的空闲时间超过了360分钟,该会话的状态就会变为SNIPED。而不是360分钟后清理掉SNIPED的会话。
2、SNIPED会话何时被清理?
当被标记为SNIPED的会话的客户端再次发出SQL语句时,客户端会收到错误提示,比如ORA-02396: exceeded maximum idle time, please connect again。这时,数据库才会彻底清理掉该会话及操作系统上的连接。
但这样一来,意味着如果客户端不发出SQL,则不能清理掉的SNIPED的会话及其使用的连接,它们仍然会占用着资源,这可能引起资源不足的报错,比如连接数达到最大的问题。这时,就需要手工来清理这些SINPED会话及其所使用的连接。
3、手工清理SNIPED会话的脚本
#!/bin/sh
tmpfile=/tmp/tmp.$$
sqlplus system/manager <
spool $tmpfile
select p.spid from v\$process p,v\$session s
where s.paddr=p.addr
and s.status in ('INACTIVE,'SNIPED');
spool off
EOF
for x in `cat $tmpfile | grep "^[0123456789]"`
do
kill -9 $x
done
rm $tmpfile
当你的数据库连接方式为共享连接时,要小心不要把分配器进程或共享服务器进程也一并杀掉了。
对于10.2版本以上的数据库且是专用连接方式的,ORACLE推荐使用:
ALTER SYSTEM DISCONNECT SESSION ',' IMMEDIATE 来清理。
而对于10.2版本以前,或者是共享连接方式的,只能直接使用从操作系统层面上把相应的进程杀掉的办法。
4、参考的文档:
在该文档中,有这样一句话:
On occasions we see conditions where a database session has a V$SESSION.STATUS = SNIPED ... and the entry never goes away . This condition can be achieved by implementing Database Resource Limits + Profiles without DCD and allow the database session to exceed the limit in the profile
其大意是:当我们发现v$session中有STATUS列为SNIPED,而且从未被清除时,通常是因为实施了数据库资源限制,使用了没有死连接检测特性(DCDDead Connection Detection)的PROFILE,而且允许数据库会话超出在PROFILE中的限制。
所以,从这段话来说,如果我们改变这些条件,也许可以避免这种情况的发生。