如何安全快速的批量删除Oracle数据库外部会话session

【前言】
有些时候,我们需要删除Oracle数据库中的一些会话连接,手动kill session 太low,费力易出错,有没有更好的方法,最好一条指令就可以搞定,本文针对此话题畅谈下。

在ORACLE数据库杀掉会话进程有三种方式:

1: ALTER SYSTEM KILL SESSION
关于KILL SESSION Clause ,如下官方文档描述所示,alter system kill session实际上不是真正的杀死会话,它只是将会话标记为终止。等待PMON进程来清除会话。

The KILL SESSION clause lets you mark a session as terminated, roll back ongoing transactions, release all session locks, and partially recover session resources. To use this clause, your instance must have the database open. Your session and the session to be terminated must be on the same instance unless you specify integer3.You must identify the session with the following values from the V$SESSION view:

For integer1, specify the value of the SID column.
For integer2, specify the value of the SERIAL# column.
For the optional integer3, specify the ID of the instance where the target session to be killed exists. You can find the instance ID by querying the GV$ tables.
If the session is performing some activity that must be completed, such as waiting for a reply from a remote database or rolling back a transaction, then Oracle Database waits for this activity to complete, marks the session as terminated, and then returns control to you. If the waiting lasts a minute, then Oracle Database marks the session to be terminated and returns control to you with a message that the session is marked to be terminated. The PMON background process then marks the session as terminated when the activity is complete.
Whether or not the session has an ongoing transaction, Oracle Database does not recover the entire session state until the session user issues a request to the session and receives a message that the session has been terminated.

可以使用如下方式来快速回滚事物、释放会话的相关锁、立即返回当前会话的控制权。
sql> ALTER SYSTEM KILL SESSION ‘sid,serial#’ IMMEDIATE

Specify IMMEDIATE to instruct Oracle Database to roll back ongoing transactions, release all session locks, recover the entire session state, and return control to you immediately.

2: ALTER SYSTEM DISCONNECT SESSION

ALTER SYSTEM DISCONNECT SESSION 杀掉专用服务器(DEDICATED SERVER)或共享服务器的连接会话,它等价于从操作系统杀掉进程。它有两个选项POST_TRANSACTION和IMMEDIATE, 其中POST_TRANSACTION表示等待事务完成后断开会话,IMMEDIATE表示中断会话,立即回滚事务。
SQL> ALTER SYSTEM DISCONNECT SESSION ‘sid,serial#’ POST_TRANSACTION;
SQL> ALTER SYSTEM DISCONNECT SESSION ‘sid,serial#’ IMMEDIATE;

3: KILL -9 SPID (Linux) 或 orakill ORACLE_SID spid (Windows)
可以使用下面SQL语句找到对应的操作系统进程SPID,然后杀掉。当然杀掉操作系统进程是一件危险的事情,尤其不要误杀。所以在执行前,一定要谨慎确认。

SET LINESIZE 100
COLUMN spid FORMAT A10
COLUMN username FORMAT A10
COLUMN program FORMAT A45
 
SELECT s.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program
FROM gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
WHERE s.type != 'BACKGROUND';

在数据库如果要彻底杀掉一个会话,尤其是大事务会话,最好是使用两种方式:

  1. 使用ALTER SYSTEM DISCONNECT SESSION IMMEDIATE
  2. OS层操作,使用下面步骤:
    1:首先在操作系统级别Kill掉进程。
    2:在数据库内部KILL SESSION
    或者反过来亦可。这样可以快速终止进程,释放资源。

针对方法1,可以使用如下
#oracle中批处理删除外部连接session

SET LINESIZE 100
COLUMN spid FORMAT A10
COLUMN username FORMAT A10
COLUMN program FORMAT A45

declare cursor mycur is 
SELECT s.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program
FROM gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
WHERE s.type != 'BACKGROUND' and s.username not like '%SYS%';
SYS@groupts> SELECT s.inst_id,
  2  s.sid,
  3  s.serial#,
  4  p.spid,
  5  s.username,
  6  s.program
  7  FROM gv$session s
  8  JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
  9  WHERE s.type != 'BACKGROUND' and s.username not like '%SYS%';

   INST_ID        SID    SERIAL# SPID       USERNAME   PROGRAM
---------- ---------- ---------- ---------- ---------- ---------------------------------------------
         1        817      28719 20371      TEST_LY    sqlplus@GBACKUP (TNS V1-V3)
begin 
for cur in mycur 
loop 
execute immediate ( 'alter system kill session '''||cur.sid || ','|| cur.SERIAL# ||''' '); 
end loop; 
end; 
/

#根据计算机名批量删除会话,具体删除条件可以自行调整上面的查询语句。

上述源代码可详见本人github,链接如下:
https://github.com/polestarYang/oracle-git/blob/master/del_external_sessions.sh

declare cursor mycur is 
select b.sid,b.serial# from v$session b where b.MACHINE = 'svctag-79bp23x' and b.STATUS = 'INACTIVE';

begin 
for cur in mycur 
loop 
execute immediate ( 'alter system kill session '''||cur.sid || ','|| cur.SERIAL# ||''' '); 
end loop; 
end; 
/

【结语】

  1. 本文讲述了oracle库上执行shutdown immediate命令时执行时间过长原因以及如何解决;

  2. 实际生产中推荐两种方法批量删除会话:

方法1:ALTER SYSTEM DISCONNECT SESSION ‘sid,serial#’ IMMEDIATE; ;
方法2:ps aux |grep “LOCAL=NO” |awk ‘{printf “%s\n”, $2}’ |xargs kill -9

关注个人微信公众号“一森咖记”
在这里插入图片描述

发布了54 篇原创文章 · 获赞 3 · 访问量 5494

猜你喜欢

转载自blog.csdn.net/db_murphy/article/details/103869534
今日推荐