当前位置: 首页 > 工具 > 正文

我们的文章会在微信公众号IT民工的龙马人生博客网站 ( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

在周末时一位朋友咨询有没有自动杀会话的脚本,今天就和大家分享一下自己常用的两个杀会话的脚本。杀会话这个工作本身来说非常的简单,但是在日常工作中怎么能把杀会话的效率做到极致是我们衡量的一个标准,因为在系统紧急故障时,我们需要通过杀会话来快速恢复系统,如果杀会话的速度跟不上,那整个系统就直接挂了。记得曾经在驻场时就出现过两次类似的情况:一次是国庆值班时,跟值班的人坐在一起,旁边值班工程师给甲方打电话,说数据库会话有异常,要求DBA赶快速度,我听到后立马登录数据库,执行一次we.sql脚本,定位到有异常的会话,立马执行kill session的脚本,整个过程不到一分钟,等我杀完会话后,接到甲方人员的电话,我立马回复,目前数据库已经正常。另外还一次是某系统运行在VMware平台,每次收到监控告警到整个Hang住时间不会超过2分钟,所以后续收到监控告警后,上去里面就是一顿咔咔的杀,杀两遍会话后数据库最少不会Hang,保证了数据库的连续性。很多数据库运维的工作其实不在难度,而在于熟练度和效率,想要提升熟练度和效率,脚本是我们最好的方式。

脚本的获取

关注公众号,后台回复“脚本”二字,已经关注并回复过的就直接下载即可。

kill_sess_80.sql

这个脚本主要的目的当数据库Process数达到参数Process配置的80%的时候,就会根据last_call_etl来降序排列非活动的会话,每次杀排名前9的会话,直到当前进程数低于80%。这个脚本的目的主要是用于医疗、企业、能源等多个行业中。

关键代码如下:

    SELECT ROUND (v1 / v2, 2)
      INTO v_count
      FROM (SELECT COUNT (*) v1 FROM v$session) a,
           (SELECT VALUE v2
              FROM v$parameter
             WHERE name = 'processes') b;

    WHILE v_count > 0.8
    LOOP
        FOR cur_session
            IN (SELECT *
                  FROM (  SELECT sid, serial#, last_call_et
                            FROM v$session s
                           WHERE     s.username NOT IN ('SYSTEM',
                                                        'SYS',
                                                        'SYSMAN',
                                                        'DBSNMP')
                                 AND S.USERNAME IS NOT NULL
                                 AND s.status = 'INACTIVE'
                                 AND s.machine <>
                                         SYS_CONTEXT ('userenv', 'host')
                        ORDER BY 3 DESC)
                 WHERE ROWNUM < 10)
        LOOP

使用方法

sqlplus '/ as sysdba'登录数据库

@kill_sess_80.sql

kill_sess_by_where.sql

在杀会话时,我们常常会改变各种杀会话的条件,比如上面的根据last_call_et也有可能根据program或者具体的sid来杀会话,所以感觉手里面永远都缺少一个杀会话的脚本,所以后面引用国外大佬的snapper.sql的脚本中的一段代码来编写了一个通用的杀会话的脚本,可以自定很多条件,也可以自定义select查询条件。

目前脚本支持接下面的这种条件:

con_id=   
sid=      
audsid=   
user=     
username= 
machine=  
program=  
service=  
module=   
action=   
osuser=   
client_id=
spid=     
ospid=    
pid=      
qcsid=    
qc=       
all       
fg        
select    
(         

其中的核心代码如下:

过滤条件部分:
    -- compute sid_filter
    case
        when trim(lower('&ssid_begin')) like 'con_id=%'    then lv_sid_filter   := 's.con_id in ('||get_filter('&ssid_begin')||')';
        when trim(lower('&ssid_begin')) like 'sid=%'       then lv_sid_filter   := 's.sid in ('   ||get_filter('&ssid_begin')||')'; 
        when trim(lower('&ssid_begin')) like 'audsid=%'    then lv_sid_filter   := 's.audsid in ('||get_filter('&ssid_begin')||')'; 
        when trim(lower('&ssid_begin')) like 'user=%'      then lv_sid_filter   := 'lower(username) like '''         ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'username=%'  then lv_sid_filter   := 'lower(username) like '''         ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'machine=%'   then lv_sid_filter   := 'lower(machine) like '''          ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'program=%'   then lv_sid_filter   := 'lower(program) like '''          ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'service=%'   then lv_sid_filter   := 'lower(service_name) like '''     ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'module=%'    then lv_sid_filter   := 'lower(module) like '''           ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'action=%'    then lv_sid_filter   := 'lower(action) like '''           ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'osuser=%'    then lv_sid_filter   := 'lower(osuser) like '''           ||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'client_id=%' then lv_sid_filter   := 'lower(client_identifier) like '''||get_filter('&ssid_begin')||'''';
        when trim(lower('&ssid_begin')) like 'spid=%'      then lv_sid_filter   := '(s.inst_id,s.paddr) in (select /*+ UNNEST */ inst_id,addr from gv$process where spid in ('||get_filter('&ssid_begin')||'))';
        when trim(lower('&ssid_begin')) like 'ospid=%'     then lv_sid_filter   := '(s.inst_id,s.paddr) in (select /*+ UNNEST */ inst_id,addr from gv$process where spid in ('||get_filter('&ssid_begin')||'))';
        when trim(lower('&ssid_begin')) like 'pid=%'       then lv_sid_filter   := '(s.inst_id,s.paddr) in (select /*+ UNNEST */ inst_id,addr from gv$process where spid in ('||get_filter('&ssid_begin')||'))';
        when trim(lower('&ssid_begin')) like 'qcsid=%'     then lv_sid_filter   := '(s.inst_id,s.sid)   in (select /*+ NO_UNNEST */ inst_id,sid from gv$px_session where qcsid in ('||get_filter('&ssid_begin')||'))';
        when trim(lower('&ssid_begin')) like 'qc=%'        then lv_sid_filter   := '(s.inst_id,s.sid)   in (select /*+ NO_UNNEST */ inst_id,sid from gv$px_session where qcsid in ('||get_filter('&ssid_begin')||'))';
        when trim(lower('&ssid_begin')) like 'all%'        then lv_sid_filter   := '1=1 and type=''USER''';
        when trim(lower('&ssid_begin')) like 'fg%'         then lv_sid_filter   := 'type=''USER''';
        when trim(lower('&ssid_begin')) like 'select%'     then lv_sid_filter   := q'{(s.inst_id,s.sid) in (&snapper_sid)}';
        when trim(lower('&ssid_begin')) like '(%'          then lv_inst_filter  := '/* inst_filter2 */ 1=1'; lv_sid_filter := q'{(s.inst_id,s.sid) in (&snapper_sid)}'; 
        else                                                    lv_sid_filter   := '/* sid_filter_else_cond */ s.sid in ('||get_filter('&ssid_begin')||')'; 
    end case;
    
    

      FOR cur_session    IN
            (SELECT * FROM gv$session s
                WHERE    1=1
                and &sid_filter
              )
    LOOP
        BEGIN

        if (cur_session.inst_id <> userenv('instance')) then
          v_sid:=cur_session.sid||','||cur_session.serial#||',@'||cur_session.inst_id;
        else
          v_sid:=cur_session.sid||','||cur_session.serial#;
        end if;

        v_sql :='alter system kill session '|| CHR (39)||v_sid|| CHR (39)|| ' immediate';

杀会话的命令:
        Execsql (cur_session.program||':'||cur_session.username||':'||cur_session.inst_id||':'||cur_session.sid||':'||cur_session.status,v_sql, debug);
        EXCEPTION
            WHEN OTHERS THEN
              DBMS_OUTPUT.put_line('Find Error on :'||SQLERRM||':'||cur_session.sid);
        END;

使用方法

@kill_sess_by_where.sql <筛选条件> [调试模式]

参数说明:

  • &1:筛选条件(必需),可以参考上面内容
  • &2:调试模式,1=仅显示KILL命令,0=实际执行KILL操作(可选,默认1)

常用使用案例

1. 按用户名终止会话

@kill_sess_by_where.sql "user=SCOTT" 0
-- 终止所有用户名为SCOTT的会话

2. 按机器名终止会话

@kill_sess_by_where.sql "machine=server01" 0
-- 终止来自server01机器的所有会话

3. 按程序名终止会话

@kill_sess_by_where.sql "program=sqlplus" 0
-- 终止所有sqlplus程序的会话

4. 按模块名终止会话

@kill_sess_by_where.sql "module=MyApp" 0
-- 终止模块名为MyApp的所有会话

5. 按服务名终止会话

@kill_sess_by_where.sql "service=MYDB" 0
-- 终止连接到MYDB服务的所有会话

6. 按SID终止特定会话

@kill_sess_by_where.sql "sid=123" 0
-- 终止SID为123的会话

还有更多的使用方法大家可以参考一下。

——————作者介绍———————–
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)


DBA必备脚本:一键杀会话:等您坐沙发呢!

发表评论

gravatar

? razz sad evil ! smile oops grin eek shock ??? cool lol mad twisted roll wink idea arrow neutral cry mrgreen

快捷键:Ctrl+Enter