RESOURCE_LIMIT determines whether resource limits are enforced in database profiles.
Values:
TRUE:Enables the enforcement of resource limits
FALSE:Disables the enforcement of resource limits
本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | set sqlblanklines on CREATE OR REPLACE PROCEDURE P_kill_session_LHR AS ----------------------------------------------------------------------------------- -- Created on 2013-06-25 12:05:07 by lhr -- Changed on 2015-08-05 12:05:07 by lhr -- function: 杀掉10个小时之前的会话 ,告警日志中会记录被杀掉的会话信息 ----------------------------------------------------------------------------------- EGIN -- IF to_char(SYSDATE, 'HH24') >= '20' OR -- TO_CHAR(SYSDATE, 'HH24') <= '08' THEN FOR cur IN (SELECT A.USERNAME, A.LOGON_TIME, A.STATUS, A.SID, A.SERIAL#, A.MACHINE, A.OSUSER, 'ALTER SYSTEM DISCONNECT SESSION ''' || a.SID || ',' || a.serial# || ''' IMMEDIATE' kill_session FROM v$session A WHERE A.STATUS IN ('INACTIVE') AND A.USERNAME IS NOT NULL AND A.LAST_CALL_ET >= 60 * 60 * 10) LOOP BEGIN EXECUTE IMMEDIATE cur.kill_session; EXCEPTION WHEN OTHERS THEN NULL; END; END LOOP; -- END IF; EXCEPTION WHEN OTHERS THEN NULL; END P_kill_session_LHR; / BEGIN --DBMS_SCHEDULER.drop_job('JOB_P_kill_session_LHR'); DBMS_SCHEDULER.CREATE_JOB(JOB_NAME => 'JOB_P_kill_session_LHR', JOB_TYPE => 'STORED_PROCEDURE', JOB_ACTION => 'P_kill_session_LHR', repeat_interval => 'FREQ=MINUTELY;INTERVAL=60', ENABLED => TRUE, START_DATE => SYSDATE, COMMENTS => '删除--每60分钟检查一次'); END; / SELECT d.job_name,d.job_action,d.run_count FROM dba_scheduler_jobs d WHERE d.job_name='JOB_P_KILL_SESSION_LHR'; |
运行日志:
| SELECT * FROM dba_scheduler_job_run_details d WHERE d.job_name='JOB_P_KILL_SESSION_LHR'; |
oracle死连接(DC)和不活动会话(INACTIVE)
This note explains the difference between a dead connection and an INACTIVE session in v$session. It also discusses the mechanisms provided to automate the cleanup of each.
这里解释死连接和不活动会话的区别,也会讨论自动清除的机制。
Difference between INACTIVE sessions and Dead Connections
Dead connections and INACTIVE sessions are different issues. Oracle provides separate mechanisms to automate the cleanup of each.
死连接和不活动会话的不同问题,oracle提供了分离的机制去自动清理。
(1) Dead connections:死连接
These are previously valid connections with the database but the connection between the client and server processes has terminated abnormally.
有些之前合法的连接,但是由于客户端和服务器进程的异常中断。
Examples of a dead connection:
- A user reboots/turns-off their machine without logging off or disconnecting from the database.
- A network problem prevents communication between the client and the server.
1.用户没有注销就关闭机器。
2.网络在客户端和服务器端终端连接。
In these cases, the shadow process running on the server and the session in the database may not terminate. To automate the cleanup of these sessions, you can use the Dead Connection Detection (DCD) feature of Net8.
这种情况下,后台进程跑在服务器端,而会话在数据库端不会中断。
When DCD is enabled, Net8 (server-side) sends a packet to the client. If the client is active, the packet is discarded. If the client has terminated, the server will receive an error and Net8 (server-side) will end that session.
当死连接启动,NET8(服务端)会发送一个包到客户端。如果客户端是活动的,这个包就被丢掉。如果客户端已经被中断,服务器端将接收一个错误,将会中断该会话。SQLNET.EXPIRE_TIME.
Refer to Note:151972.1: Dead Connection Detection (DCD) Explained, for details regarding DCD.
(2) INACTIVE Sessions:
These are sessions that remain connected to the database with a status in v$session of INACTIVE.
会话与服务器端保持连接,但是状态为inactive.
Example of an INACTIVE session: - A user starts a program/session, then leaves it running and idle for an extended period of time.
用户开始一个会话,运行一段时间后,保持相当一段时间的空闲。
To automate cleanup of INACTIVE sessions you can create a profile with an appropriate IDLE_TIME setting and assign that profile to the users.
自动清理不活动的会话,你可以创一个profile.然后设置恰当的IDLE_TIME,分配给指定用户。
Note:159978.1: How To Automate Disconnection of Idle Sessions, outlines the steps to setup IDLE_TIME for this.kill session相关内容
kill session 是DBA经常碰到的事情之一。如果kill 掉了不该kill 的session,则具有破坏性,因此尽可能的避免这样的错误发生。同时也应当注意,如果kill 的session属于Oracle 后台进程,则容易导致数据库实例宕机。
一、获得需要kill session的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | SET LINESIZE 180 COLUMN spid FORMAT A10 COLUMN username FORMAT A10 COLUMN program FORMAT A40 SELECT s.inst_id, s.sid, s.serial#, p.spid, s.username, s.program, s.paddr, s.STATUS FROM gv$session s JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id WHERE s.type != 'BACKGROUND'; INST_ID SID SERIAL# SPID USERNAME PROGRAM PADDR STATUS ---------- ---------- ---------- ---------- ---------- ---------------------------------------- ---------------- -------- 1 125 5 14029 SYS sqlplus@orcltest (TNS V1-V3) 0000000077C98660 INACTIVE 1 9 15 14274 SYS sqlplus@orcltest (TNS V1-V3) 0000000077C99710 INACTIVE 1 17 5 14078 LHR sqlplus.exe 0000000077CA5F50 INACTIVE 1 144 31 14645 SYS sqlplus@orcltest (TNS V1-V3) 0000000077CA7000 ACTIVE 1 20 7 14647 SYS plsqldev32.exe 0000000077CA80B0 INACTIVE 1 145 23 14651 SYS plsqldev32.exe 0000000077CA9160 INACTIVE |
二、使用ALTER SYSTEM KILL SESSION 命令实现
语法:
SQL> ALTER SYSTEM KILL SESSION 'sid,serial#';
SQL> ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
对于RAC环境下的kill session ,需要搞清楚需要kill 的session 位于哪个节点,可以查询GV$SESSION视图获得。11g杀掉集群环境下的某个会话:
alter system kill session'1228,42549,@实例号';
例如:alter system kill session '1228, 42549, @2';
10g下应登录到某个特定的实例才可以。
Kill session 命令实际不会kill session,比如等待远程数据库的反应或者回滚事务,那么session 就不会立即kill其必须等待当前的操作结束才能执行,在这种情况下,session 就会被标记为killed 状态。
我们可以在kill 命令中添加immediate,语法如下:
SQL> ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
这个命令不会影响性能,但它会立即返回到当前的session,处理kill操作,而不是等待其他的信息完成。 如果session 一直处于killed 状态,那么可以考虑在操作系统级别kill掉相关的进程。不过在操作之前,要先确认session 是否在执行rollback 操作。 可以使用如下SQL 来确认。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | SET LINESIZE 200 COLUMN username FORMAT A15 SELECT s.username, s.sid, s.serial#, t.used_ublk, t.used_urec, rs.segment_name, r.rssize, r.status FROM v$transaction t, v$session s, v$rollstat r, dba_rollback_segs rs WHERE s.saddr = t.ses_addr AND t.xidusn = r.usn AND rs.segment_id = t.xidusn ORDER BY t.used_ublk DESC; |
如果有我们的session,那么就要等rollback 先完成,然后才能在操作系统级别kill session。
kill session 的时候仅仅是将会话杀掉。在有些时候,由于较大的事务或需要运行较长的SQL语句将导致需要kill的session并不能立即杀掉。对于这种情况将收到 "marked for kill"提示(如下),一旦会话当前事务或操作完成,该会话被立即杀掉。
| alter system kill session '4730,39171' * ERROR at line 1: ORA-00031: session marked for kill |
在下面的操作中将杀掉会话146,144
| sys@AUSTIN> alter system kill session '146,23'; System altered. sys@AUSTIN> alter system kill session '144,42'; System altered. sys@AUSTIN> select inst_id,saddr,sid,serial#,paddr,username,status,program from gv$session where username is not null; INST_ID SADDR SID SERIAL# PADDR USERNAME STATUS PROGRAM ---------- -------- ---------- ---------- -------- ---------- -------- --------------------------------------------- 1 4C70BF04 144 42 4C6545A0 SCOTT KILLED sqlplus@oracle10g (TNS V1-V3) 1 4C70E6B4 146 23 4C6545A0 TEST KILLED sqlplus@oracle10g (TNS V1-V3) 1 4C71FC84 160 17 4C624174 SYS ACTIVE sqlplus@oracle10g (TNS V1-V3) SQL> select sid,serial#,server,status from v$session where sid=22; SID SERIAL# SERVER STATUS ---------- ---------- --------- -------- 22 7 PSEUDO KILLED |
注意:在查询中可以看到被杀掉的会话的PADDR地址发生了变化,参照查询结果中的红色字体。如果多个session被kill 掉,则多个session的PADDR被改为相同的进程地址,被杀掉的会话的server列变为PSEUDO。
oracle killed会话不释放的问题
一般情况下,在杀一个会话的时候,直接执行alter system kill session ‘sid,serial#’;
Administrator's Guide说,当session是active的时候,alter system kill session 只是将session的状态标识为killed,server变为pseudo状态,并不会释放session持有的资源,所以我们在执行完alter system kill session 后,看会话还是一直存在。
这种情况下可以使用 immediate选项,强制立即Kill会话,如下:
SQL> alter system kill session '3964,51752' immediate;
SQL Language Reference(http://docs.oracle.com/cd/B28359_01/server.111/b28286/toc.htm#BEGIN)
里对Immediate的解释是: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.
killed状态的会话如何找到spid列
一般情况下我们查询会话的后台进程是通过如下的SQL,即通过v$session的paddr列关联v$process的addr列,但是killed状态的v$session的paddr列都变成了一样的,所以已经没有办法通过如下的SQL去查询了。
| SELECT b.SID, b.SERIAL# , c.SPID, b.status FROM v$session b , v$process c WHERE b.PADDR=c.ADDR AND b.sid=???; |
如果会话已经在v$sesion里是killed状态,那么我们通过上面的SQL已经查不出spid,可以用下面的SQL查出SPID:
-----方法1
| select spid, program from v$process where program!= 'PSEUDO' and addr not in (select paddr from v$session) and addr not in (select paddr from v$bgprocess) and addr not in (select paddr from v$shared_server); select INST_ID, spid, program,'kill -9 '|| spid kill9 from gv$process a where program != 'PSEUDO' and (INST_ID, addr) not in (select INST_ID, paddr from gv$session) and (INST_ID, addr) not in (select INST_ID, paddr from gv$bgprocess) and (INST_ID, addr) not in (select INST_ID, paddr from gv$shared_server) and a.PNAME is null; |
-----方法2 我自己常用的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | set line 9999 col sessionid format a20 col sessionid_killed format a20 col kill_session format a60 SELECT a.INST_ID, a.SID || ',' || a.SERIAL# || ',' || (select spid from gv$process b where b.INST_ID = a.INST_ID and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR ) sessionid, a.PADDR, a.STATUS, a.PROGRAM, 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session FROM gv$session a WHERE a.USERNAME = 'SYS' and a.STATUS = 'KILLED'; |
As a result of the bug, 2 additional columns have been added to V$SESSION from 11g on:
V$SESSION
CREATOR_ADDR - state object address of creating process
CREATOR_SERIAL# - serial number of creating process
CREATOR_ADDR is the column that can be joined with the ADDR column in V$PROCESS to uniquely identify the killed process corresponding to the former session.
Following the previous example, this would identify the killed session
-----方法3
| SELECT a.SID || ',' || a.SERIAL# || ',' || (select spid from gv$process b where b.INST_ID = a.INST_ID and A.pid = b.pid) sessionid, 'alter system kill session ''' || sid || ',' || serial# || ''';' kill_session FROM gV$DETACHED_SESSION a; |
-----方法4
| SELECT INST_ID, spid, program, 'kill -9 ' || spid kill9 FROM gv$process a WHERE (a.INST_ID, a.addr) in (select INST_ID, p.addr from gv$process p where pid <> 1 minus select INST_ID, s.paddr from gv$session s) and a.PNAME is null; |
-----方法4
| SELECT s.SID, s.username,s.status, x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP, decode(bitand(x.ksuprflg,2),0,null,1) FROM x$ksupr x,v$session s WHERE s.paddr(+)=x.addr and bitand(ksspaflg,1)!=0 ; |
为何killed状态的进程一直在v$session中能查询到?
[ID 100859.1]这篇文章中提到pmon如何清理killed的会话:
PMON will not delete the session object itself until the client connected to
that session notices that it has been killed. Therefore, the sequence of
events is:
1) alter system kill session is issued - the STATUS of the session object in
V$SESSION becomes KILLED, its server becomes PSEUDO.
2) PMON cleans up the resources allocated to the session
(i.e., rolls back its transaction, releases its locks, etc).
3) the entry in V$SESSION remains there until the client of that session (the
client is the process associated with the OSUSER,MACHINE,PROCESS columns in
the V$SESSION view) tries to do another request.
4) the client attempts another SQL statement and gets back ORA-28.
5) PMON can now remove the entry from V$SESSION.
This behavior is necessary because the client still has pointers to the
session object even though the session has been killed. Therefore, the
object cannot be deleted until the client is no longer pointing at it.
alter system kill session后,会话状态变为killed,pmon回收资源后,会话的信息仍然保留在v$session中,直到客户端再次请求,数据库返回ORA-28错误:"your session has been killed"。
此时pmon才从v$session中移除这些会话的信息。而上述中,客户端机器重启,无法再向数据库发送请求,因此从v$session中一直可以查到,只有通过操作系统强制杀掉进程,才能触发pmon从v$session中清除。
然后Oracle就等待PMON去清除这些Session.所以通常等待一个被标记为Killed的Session退出需要花费很长的时间.如果此时被Kill的process,重新尝试执行任务,那么马上会收到进程中断的提示,process退出,此时Oracle会立即启动PMON来清除该session.这被作为一次异常中断处理.
为何kill session后,paddr变成同一个值了?
[ID 387077.1]这篇文章中提到:
Bug 5453737 WHEN A SESSION IS KILLED, PADDR CHANGES IN V$SESSION BUT ADDR NOT IN V$PROCESS closed as not a bug with the following explanation:
When a session is killed, the session state object(and all the child state objects under the session state object) move out from under the original parent process state object, and are placed under the pseudo process state object (which is expected, given the parent/child process mechanism on Unix). PMON will clean up all the state objects found under the pseudo process state object. That explains why PADDR changes in V$SESSION when a session is killed. New PADDR you are seeing in v$SESSION is the address of the pseudo process state object. This shows up in system state under PSEUDO PROCESS for group DEFAULT: V$PROCESS still maintains the record of the original parent process. This is expected.
使用以下sql查找killed状态的spid:
select spid, program from v$process
where program!= 'PSEUDO'
and addr not in (select paddr from v$session)
and addr not in (select paddr from v$bgprocess)
and addr not in (select paddr from v$shared_server);
通过底层表x$ksupr关联v$session也可以,11.1.0.6版本及更高在v$session增加了2个字段CREATOR_ADDR和CREATOR_SERIAL#用于标记这种情况。然后就可以通过操作系统命令kill -9来杀掉这些进程了。
ALTER SYSTEM KILL SESSION 权限不足
需要赋权限,dba角色不用,grant alter system to lhr;
授予普通用户杀自己session的权限
若没有dba角色或者没有alter system权限的话,业务用户就不能自己杀自己会话了,这样一来,只能dba来介入了,其实这个功能我们可以通过如下的SQL脚本来完成。
------- user replace XXXXXX
------- 普通用户可以kill自己的session 授予应用用户杀自己session的权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | create or replace view vw_myownersession_lhr as select * from v$session where username = USER; create or replace public synonym syn_myownersession_lhr for sys.vw_myownersession_lhr; create or replace procedure pro_kill_myown_session_lhr( p_sid in varchar2,p_serial# in varchar2) is cursor_name pls_integer default dbms_sql.open_cursor; ignore pls_integer; BEGIN select count(*) into ignore from v$session where username = USER and sid = p_sid and serial# = p_serial# ; if ( ignore = 1 ) then dbms_sql.parse(cursor_name,'alter system disconnect session '''||p_sid||','||p_serial#||''' immediate',dbms_sql.native); ignore := dbms_sql.execute(cursor_name); else raise_application_error( -20001,'You do not own session ''' ||p_sid || ',' || p_serial# ||'''' ); end if; END pro_kill_myown_session_lhr; / create or replace public synonym pro_kill_session_lhr for sys.pro_kill_myown_session_lhr; grant select on syn_myownersession_lhr to XXXXXX; grant execute on pro_kill_session_lhr to XXXXXX; SELECT USERENV('SID') FROM DUAL; select sid,serial#,paddr,status from syn_myownersession_lhr where sid=19; exec pro_kill_session_lhr(19,15); |
ALTER SYSTEM DISCONNECT SESSION 说明
Alter system disconnect session 是一个可选的kill session 的方法。 与kill session 命令不同,disconnect session 命令会kill 掉 dedicated server process, 该命令等同于在操作系统级别kill 掉server process。
具体语法如下:
SQL> ALTER SYSTEM DISCONNECT SESSION'sid,serial#' POST_TRANSACTION;
SQL> ALTER SYSTEM DISCONNECT SESSION'sid,serial#' IMMEDIATE;
POST_TRANSACTION 选项会等待事务完成之后在断开连接。
IMMEDIATE 选项会立即断开连接,然后事务会进行recover操作。
这2个选项也可以一起使用,但是必须指定其中一个,否则就会报错:
SQL> alter system disconnect session'30,7';
alter system disconnect session '30,7'
*
ERROR at line 1:
ORA-02000: missing POST_TRANSACTION orIMMEDIATE keyword
SQL>
SQL> alter system disconnect session'15,12' post_transaction immediate;
System altered.
使用alter system disconnectsession 命令就不需要切换到系统来kill session,也从而减少了kill 错进程的几率。
PMON 清理间隔
PMON进程负责处理异常结束进程相关资源的释放。PMON周期性地被唤醒,可以对"_PKT_PMON_INTERVAL"这个隐藏参数来进行修改,默认为50秒。也可以通过查找出进程的PID,然后在oradebug中,执行命令oradebug wakeup orapid(oracle进程的PID,不是OS的PID)来手动唤醒PMON进程。可以用alter session set events '100246 trace name conext forever,level 4'来查看PMON的相关操作。
| SYS@LHRDGZK1> SELECT a.INDX, 2 a.KSPPINM NAME, 3 a.KSPPDESC, 4 b.KSPPSTVL 5 FROM x$ksppi a, 6 x$ksppcv b 7 WHERE a.INDX = b.INDX 8 and lower(a.KSPPINM) like lower('%¶meter%'); Enter value for parameter: _PKT_PMON_INTERVAL old 8: and lower(a.KSPPINM) like lower('%¶meter%') new 8: and lower(a.KSPPINM) like lower('%_PKT_PMON_INTERVAL%') INDX NAME KSPPDESC KSPPSTVL ----- ---------------------- ------------------------------------ -------------------- 61 _pkt_pmon_interval PMON process clean-up interval (cs) 50 alter system set "_PKT_PMON_INTERVAL"=5; |
MOS上的一些资料
于是metalink和google到以下一些资料:
Removing Sessions in Killed Status on Unix [ID 274216.1]
ALTER SYSTEM KILL Session Marked for Killed Forever [ID 1020720.102]
KILLING INACTIVE SESSIONS DOES NOT REMOVE SESSION ROW FROM V$SESSION [ID 1041427.6]
ALTER SYSTEM KILL SESSION does not Release Locks Killing a Thread on Windows NT [ID 100859.1]
http://blog.csdn.net/tianlesoftware/article/details/7417058
http://www.eygle.com/faq/Kill_Session.htm
---比较有用的
How To Find The Process Identifier (pid, spid) After The Corresponding Session Is Killed? [ID 387077.1]
HOW TO HAVE ORACLE CLEAN-UP OLD USER INFO AFTER KILLING SESSION UNDER MTS Note:1023442.6
实验部分
实验环境介绍
项目 | primary db |
---|
db 类型 | 单实例 |
db version | 11.2.0.3.0 |
db 存储 | ASM |
主机IP地址/hosts配置 | 192.168.59.129 |
OS版本及kernel版本 | rhel 6.5 |
实验内容
实验序号 | 实验内容 |
---|
1 | 设置用户profile的idle_time 参数 |
2 | kill session的时候加immediate和不加的区别 |
3 | 授予普通用户kill自己用户的权限 |
4 | KILLED状态的会话如何找到相关的SPID |
实验过程
设置用户profile的idle_time 参数
可以参考:
http://blog.csdn.net/leshami/article/details/9184917
http://blog.csdn.net/tianlesoftware/article/details/6238279
设置resource_limit 为true,该参数默认为false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | [oracle@orcltest ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.3.0 Production on Sun Jun 26 17:55:53 2016 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> show parameter RESOURCE_LIMIT NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ resource_limit boolean FALSE SQL> alter system set resource_limit=true; System altered. 为业务用户创建profile文件。然后把该配置文件赋给业务用户。 SQL> create profile pro_lhr limit idle_time 1; Profile created. SQL> alter user lhr profile pro_lhr; User altered. SQL> SQL> set line 9999 pagesize 9999 SQL> select * from dba_profiles where profile='PRO_LHR'; PROFILE RESOURCE_NAME RESOURCE LIMIT ------------------------------ -------------------------------- -------- ---------------------------------------- PRO_LHR COMPOSITE_LIMIT KERNEL DEFAULT PRO_LHR SESSIONS_PER_USER KERNEL DEFAULT PRO_LHR CPU_PER_SESSION KERNEL DEFAULT PRO_LHR CPU_PER_CALL KERNEL DEFAULT PRO_LHR LOGICAL_READS_PER_SESSION KERNEL DEFAULT PRO_LHR LOGICAL_READS_PER_CALL KERNEL DEFAULT PRO_LHR IDLE_TIME KERNEL 1 PRO_LHR CONNECT_TIME KERNEL DEFAULT PRO_LHR PRIVATE_SGA KERNEL DEFAULT PRO_LHR FAILED_LOGIN_ATTEMPTS PASSWORD DEFAULT PRO_LHR PASSWORD_LIFE_TIME PASSWORD DEFAULT PRO_LHR PASSWORD_REUSE_TIME PASSWORD DEFAULT PRO_LHR PASSWORD_REUSE_MAX PASSWORD DEFAULT PRO_LHR PASSWORD_VERIFY_FUNCTION PASSWORD DEFAULT PRO_LHR PASSWORD_LOCK_TIME PASSWORD DEFAULT PRO_LHR PASSWORD_GRACE_TIME PASSWORD DEFAULT 16 rows selected. SQL> 启动一个会话,等待一分钟 D:Usersxiaomaimiao>sqlplus lhr/lhr@192.168.59.129/oratest SQL*Plus: Release 11.2.0.1.0 Production on Sun Jun 26 18:03:09 2016 Copyright (c) 1982, 2010, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options LHR@192.168.59.129/oratest> set time on 18:03:12 LHR@192.168.59.129/oratest> SELECT a.SID, 18:03:37 2 b.SERIAL# , 18:03:37 3 c.SPID, 18:03:37 4 b.status 18:03:37 5 FROM v$mystat a, 18:03:37 6 v$session b , 18:03:37 7 v$process c 18:03:37 8 WHERE a.SID = b.SID 18:03:37 9 and b.PADDR=c.ADDR 18:03:37 10 AND rownum = 1; SID SERIAL# SPID STATUS ---------- ---------- ------------------------ -------- 19 9 14689 ACTIVE 1分钟后在其它会话窗口查询: SQL> SELECT b.SID, 2 b.SERIAL# , 3 c.SPID, 4 b.status 5 FROM v$session b , 6 v$process c 7 WHERE b.PADDR=c.ADDR 8 AND b.sid=19; SID SERIAL# SPID STATUS ---------- ---------- ------------------------ -------- 19 9 14689 INACTIVE SQL> / SID SERIAL# SPID STATUS ---------- ---------- ------------------------ -------- 19 9 14689 SNIPED SQL> SQL> alter system kill session '19,9' immediate; System altered. SQL> SELECT b.SID, 2 b.SERIAL# , 3 c.SPID, 4 b.status 5 FROM v$session b , 6 v$process c 7 WHERE b.PADDR=c.ADDR 8 AND b.sid=19; no rows selected SQL> |
授予普通用户杀自己session的权限
创建普通用户lhrtest,授予resource和connect权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | SQL> create user lhrtest identified by lhrtest; User created. SQL> grant resource ,connect to lhrtest; Grant succeeded. 使用sys用户来创建需要的脚本: SQL> create or replace view vw_myownersession_lhr 2 as 3 select * from v$session where username = USER; View created. SQL> create or replace public synonym syn_myownersession_lhr for sys.vw_myownersession_lhr; Synonym created. SQL> create or replace procedure pro_kill_myown_session_lhr( p_sid in varchar2,p_serial# in varchar2) 2 is 3 cursor_name pls_integer default dbms_sql.open_cursor; 4 ignore pls_integer; 5 BEGIN 6 select count(*) into ignore 7 from v$session 8 where username = USER 9 and sid = p_sid 10 and serial# = p_serial# ; 11 12 if ( ignore = 1 ) 13 then 14 dbms_sql.parse(cursor_name,'alter system disconnect session '''||p_sid||','||p_serial#||''' immediate',dbms_sql.native); 15 ignore := dbms_sql.execute(cursor_name); 16 else 17 raise_application_error( -20001,'You do not own session ''' ||p_sid || ',' || p_serial# ||'''' ); 18 end if; 19 END pro_kill_myown_session_lhr; 20 / Procedure created. SQL> create or replace public synonym pro_kill_session_lhr for sys.pro_kill_myown_session_lhr; Synonym created. SQL> grant select on syn_myownersession_lhr to lhrtest; Grant succeeded. SQL> grant execute on pro_kill_session_lhr to lhrtest; Grant succeeded. SQL> 用windows客户端登录一个会话: D:Usersxiaomaimiao>sqlplus lhrtest/lhrtest@192.168.59.129/oratest SQL*Plus: Release 11.2.0.1.0 Production on Sun Jun 26 19:19:42 2016 Copyright (c) 1982, 2010, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options LHRTEST@192.168.59.129/oratest> SELECT USERENV('SID') FROM DUAL; USERENV('SID') -------------- 19 LHRTEST@192.168.59.129/oratest> select sid,serial#,paddr,status from syn_myownersession_lhr where sid=19; SID SERIAL# PADDR STATUS ---------- ---------- ---------------- -------- 19 15 0000000077C9B870 ACTIVE 不要关闭19,15窗口,然后重新开一个会话窗口: SQL> conn lhrtest/lhrtest Connected. SQL> show user USER is "LHRTEST" SQL> select sid,serial#,paddr,status from syn_myownersession_lhr where sid=19; SID SERIAL# PADDR STATUS ---------- ---------- ---------------- -------- 19 15 0000000077C9B870 INACTIVE SQL> alter system kill session '19,15' immediate; alter system kill session '19,15' immediate * ERROR at line 1: ORA-01031: insufficient privileges SQL> exec pro_kill_session_lhr(19,15); PL/SQL procedure successfully completed. SQL> select sid,serial#,paddr,status from syn_myownersession_lhr where sid=19; no rows selected SQL> |
可以看到普通用户也可以杀掉自己用户的会话了。
kill session的时候加immediate和不加immediate的区别
kill session 的测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | SQL> set line 9999 SQL> col sessionid format a20 SQL> col sessionid_killed format a20 SQL> col kill_session format a60 SQL> SQL> SELECT a.INST_ID, 2 a.SID || ',' || a.SERIAL# || ',' || 3 (select spid 4 from gv$process b 5 where b.INST_ID = a.INST_ID 6 and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR 7 ) sessionid, 8 a.PADDR, 9 a.STATUS, 10 a.PROGRAM, 11 a.server, 12 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session 13 FROM gv$session a 14 WHERE a.type != 'BACKGROUND'; INST_ID SESSIONID PADDR STATUS PROGRAM SERVER KILL_SESSION ---------- -------------------- ---------------- -------- ---------------------------------------- --------- ------------------------------------------------------------ 1 9,169,14901 0000000077C9B870 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '9,169' immediate; 1 20,9,14891 0000000077CA5F50 INACTIVE plsqldev32.exe DEDICATED alter system disconnect session '20,9' immediate; 1 23,35,14885 0000000077C99710 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '23,35' immediate; 1 125,7,14873 0000000077C98660 ACTIVE sqlplus@orcltest (TNS V1-V3) DEDICATED alter system disconnect session '125,7' immediate; 1 145,23,14651 0000000077CA9160 INACTIVE plsqldev32.exe DEDICATED alter system disconnect session '145,23' immediate; SQL> alter system kill session '9,169'; System altered. SQL> alter system kill session '20,9'; System altered. SQL> set line 9999 SQL> col sessionid format a20 SQL> col sessionid_killed format a20 SQL> col kill_session format a60 SQL> SQL> SELECT a.INST_ID, 2 a.SID || ',' || a.SERIAL# || ',' || 3 (select spid 4 from gv$process b 5 where b.INST_ID = a.INST_ID 6 and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR 7 ) sessionid, 8 a.PADDR, 9 a.STATUS, 10 a.PROGRAM, 11 a.server, 12 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session 13 FROM gv$session a 14 WHERE a.type != 'BACKGROUND'; INST_ID SESSIONID PADDR STATUS PROGRAM SERVER KILL_SESSION ---------- -------------------- ---------------- -------- ---------------------------------------- --------- ------------------------------------------------------------ 1 9,169,14901 0000000077D2DCF8 KILLED sqlplus.exe PSEUDO alter system disconnect session '9,169' immediate; 1 20,9,14891 0000000077D2DCF8 KILLED plsqldev32.exe PSEUDO alter system disconnect session '20,9' immediate; 1 23,35,14885 0000000077C99710 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '23,35' immediate; 1 125,7,14873 0000000077C98660 ACTIVE sqlplus@orcltest (TNS V1-V3) DEDICATED alter system disconnect session '125,7' immediate; 1 145,23,14651 0000000077CA9160 INACTIVE plsqldev32.exe DEDICATED alter system disconnect session '145,23' immediate; SQL> |
可以看到,杀掉的2个会话在v$session中都可以查到,只是①其status变为了KILLED,②server列变为了PSEUDO,③paddr列都变为了一样的了,因此这个时候如若还使用paddr列来关联process列必然查询不到spid号了,这个时候可以使用前边我们介绍的几种SQL来查询会话的spid,然后用kill -9杀掉会话。
我们用kill -9杀掉会话,等待后台PMON来自动清理进程,若是PMON很慢,我们可以手动来用oradebug wakeup 2来唤醒PMON进程,还可以设置PMON的清理间隔alter system set "_PKT_PMON_INTERVAL"=5;:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | [oracle@orcltest ~]$ ps -ef|grep 14901 oracle 14901 1 0 19:51 ? 00:00:00 oracleoratest (LOCAL=NO) oracle 14959 14625 0 20:17 pts/8 00:00:00 grep 14901 [oracle@orcltest ~]$ kill -9 14901 [oracle@orcltest ~]$ ps -ef|grep 14901 oracle 14961 14625 0 20:17 pts/8 00:00:00 grep 14901 [oracle@orcltest ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.3.0 Production on Sun Jun 26 20:17:54 2016 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> set line 9999 SQL> col sessionid format a20 SQL> col sessionid_killed format a20 SQL> col kill_session format a60 SQL> SQL> SELECT a.INST_ID, 2 a.SID || ',' || a.SERIAL# || ',' || 3 (select spid 4 from gv$process b 5 where b.INST_ID = a.INST_ID 6 and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR 7 ) sessionid, 8 a.PADDR, 9 a.STATUS, 10 a.PROGRAM, 11 a.server, 12 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session 13 FROM gv$session a 14 WHERE a.type != 'BACKGROUND'; INST_ID SESSIONID PADDR STATUS PROGRAM SERVER KILL_SESSION ---------- -------------------- ---------------- -------- ------------------------------------------------ ----------- --------------------------------------------------------- 1 9,169,14901 0000000077D2DCF8 KILLED sqlplus.exe PSEUDO alter system disconnect session '9,169' immediate; 1 20,9,14891 0000000077D2DCF8 KILLED plsqldev32.exe PSEUDO alter system disconnect session '20,9' immediate; 1 23,35,14885 0000000077C99710 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '23,35' immediate; 1 125,9,14964 0000000077C98660 ACTIVE sqlplus@orcltest (TNS V1-V3) DEDICATED alter system disconnect session '125,9' immediate; SQL> select INST_ID, spid, program,A.PNAME,A.PID 2 from gv$process a 3 where a.PNAME='PMON'; INST_ID SPID PROGRAM PNAME PID ---------- ---------- ---------------------------------------- ----- ---------- 1 13955 oracle@orcltest (PMON) PMON 2 SQL> oradebug wakeup 2 Statement processed. SQL> SQL> SET LINESIZE 180 SQL> COLUMN spid FORMAT A10 SQL> COLUMN username FORMAT A10 SQL> COLUMN program FORMAT A40 SQL> SELECT s.inst_id, 2 s.sid, 3 s.serial#, 4 p.spid, 5 s.username, 6 s.program, 7 s.paddr, 8 s.STATUS, 9 s.server 10 FROM gv$session s 11 left outer JOIN gv$process p 12 ON p.addr = s.paddr 13 AND p.inst_id = s.inst_id 14 WHERE s.type != 'BACKGROUND'; INST_ID SID SERIAL# SPID USERNAME PROGRAM PADDR STATUS SERVER ---------- ---------- ---------- ---------- ---------- ---------------------------------------- ---------------- -------- --------- 1 125 9 14964 SYS sqlplus@orcltest (TNS V1-V3) 0000000077C98660 ACTIVE DEDICATED 1 23 35 14885 SYS sqlplus.exe 0000000077C99710 INACTIVE DEDICATED 1 20 11 14966 SYS plsqldev32.exe 0000000077C9B870 INACTIVE DEDICATED 1 9 177 14968 SYS plsqldev32.exe 0000000077CA5F50 INACTIVE DEDICATED SQL> kill session immediate的测试: SQL> set line 9999 SQL> col sessionid format a20 SQL> col sessionid_killed format a20 SQL> col kill_session format a60 SQL> SQL> SELECT a.INST_ID, 2 a.SID || ',' || a.SERIAL# || ',' || 3 (select spid 4 from gv$process b 5 where b.INST_ID = a.INST_ID 6 and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR 7 ) sessionid, 8 a.PADDR, 9 a.STATUS, 10 a.PROGRAM, 11 a.server, 12 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session 13 FROM gv$session a 14 WHERE a.type != 'BACKGROUND'; INST_ID SESSIONID PADDR STATUS PROGRAM SERVER KILL_SESSION ---------- -------------------- ---------------- -------- ---------------------------------------- --------- ------------------------------------------------------------ 1 9,169,14901 0000000077D2DCF8 KILLED sqlplus.exe PSEUDO alter system disconnect session '9,169' immediate; 1 20,9,14891 0000000077D2DCF8 KILLED plsqldev32.exe PSEUDO alter system disconnect session '20,9' immediate; 1 23,35,14885 0000000077C99710 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '23,35' immediate; 1 125,7,14873 0000000077C98660 ACTIVE sqlplus@orcltest (TNS V1-V3) DEDICATED alter system disconnect session '125,7' immediate; 1 145,23,14651 0000000077CA9160 INACTIVE plsqldev32.exe DEDICATED alter system disconnect session '145,23' immediate; SQL> alter system kill session '145,23' immediate; System altered. SQL> set line 9999 SQL> col sessionid format a20 SQL> col sessionid_killed format a20 SQL> col kill_session format a60 SQL> SQL> SELECT a.INST_ID, 2 a.SID || ',' || a.SERIAL# || ',' || 3 (select spid 4 from gv$process b 5 where b.INST_ID = a.INST_ID 6 and A.creator_addr = b.ADDR --and decode(a.status,'KILLED',A.creator_addr,A.PADDR) = b.ADDR 7 ) sessionid, 8 a.PADDR, 9 a.STATUS, 10 a.PROGRAM, 11 a.server, 12 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;' kill_session 13 FROM gv$session a 14 WHERE a.type != 'BACKGROUND'; INST_ID SESSIONID PADDR STATUS PROGRAM SERVER KILL_SESSION ---------- -------------------- ---------------- -------- ---------------------------------------- --------- ------------------------------------------------------------ 1 9,169,14901 0000000077D2DCF8 KILLED sqlplus.exe PSEUDO alter system disconnect session '9,169' immediate; 1 20,9,14891 0000000077D2DCF8 KILLED plsqldev32.exe PSEUDO alter system disconnect session '20,9' immediate; 1 23,35,14885 0000000077C99710 INACTIVE sqlplus.exe DEDICATED alter system disconnect session '23,35' immediate; 1 125,7,14873 0000000077C98660 ACTIVE sqlplus@orcltest (TNS V1-V3) DEDICATED alter system disconnect session '125,7' immediate; SQL> |
可以看到若加上immediate的话会话没有事务的情况下会立即释放,且v$session视图也被清理了。
Windows平台杀后端进程orakill
由于oracle在windows平台采用了单进程多线程的实现方式,unix/linux上的server process在windows上实际是一个thread。在unix平台上,有时使用alter system kill的方式杀死一个用户会话后,可能会标记为killed而不是立即释放该会话所占有的所有资源,或者由于某些原因,某些会话处于假死状态,这时可能要在os级别强行kill对应的process。但在windows上,进程管理器中只能看到一个oracle进程,而无法看到并且杀死具体的线程。这种情况下,我们当然可以借助第三方的线程管理工具来实现我们杀某个指定线程的目的,但实际上,oracle本身也是提供了这种的工具的。这就是orakill工具。
在windows上运行的oracle,在操作系统中只会有一个oracle.exe进程,如果在关库的时候alert日志中告警hang在某个进程上,此时可以通过orakill来杀除该会话。
当手工使用“alter system kill session ‘sid,serial#’ immediate;”命令杀数据库中的session后,会话信息可能还会驻留在数据库中。使用这个orakill命令便可在操作系统一级可以彻底清除之;
C:>orakill
Usage: orakill sid thread
where sid = the Oracle instance to target
thread = the thread id of the thread to kill
The thread id should be retrieved from the spid column of a query such as:
| select spid, osuser, s.program from v$process p, v$session s where p.addr=s.paddr |
常用SQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | SELECT a.SID, b.SERIAL# , c.SPID, b.status FROM v$mystat a, v$session b , v$process c WHERE a.SID = b.SID and b.PADDR=c.ADDR AND rownum = 1; SELECT b.SID, b.SERIAL# , c.SPID, b.status FROM v$session b , v$process c WHERE b.PADDR=c.ADDR AND b.sid=???; ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE; -- Linux kill -9 spid -- windows orakill sid thread(Windows平台 SID是Oracle的实例名,thread是上面查出来的SID) |