Oracle kill session相關問題(上)

bitifi發表於2016-11-05

【會話】Oracle kill session系列

 

1.1  BLOG文件結構圖

Oracle kill session相關問題 - 3 -

1.1 BLOG文件結構圖 - 4 -

1.2 前言部分 - 5 -

1.2.1 導讀和注意事項 - 5 -

1.2.2 相關參考文章連結 - 6 -

1.2.3 本文簡介 - 7 -

1.3 相關知識點掃盲(摘自網路+個人總結) - 7 -

1.3.1 得到當前會話的幾個SQL - 7 -

1.3.2 Session 狀態說明 - 8 -

1.3.3 oracle死連線(DC)和不活動會話(INACTIVE) - 15 -

1.3.4 kill session相關內容 - 17 -

1.3.5 MOS上的一些資料 - 29 -

--------------------------------------------------------------------------------------------------------------------- - 31 -

第2章 實驗部分 - 31 -

2.1 實驗環境介紹 - 31 -

2.2 實驗內容 - 31 -

2.3 實驗過程 - 32 -

2.3.1 設定使用者profile的idle_time 引數 - 32 -

2.3.2 授予普通使用者殺自己session的許可權 - 35 -

2.3.3 kill session的時候加immediate和不加immediate的區別 - 38 -

--------------------------------------------------------------------------------------------------------------------- - 43 -

About Me - 43 -

 

1.2  前言部分

 

1.2.1  導讀和注意事項

各位技術愛好者,看完本文後,你可以掌握如下的技能,也可以學到一些其它你所不知道的知識,~O(∩_∩)O~

killed狀態的會話如何釋放(如何找到後臺程式)--重點?

授予普通使用者可以kill自己使用者session的許可權

kill sessiondisconnect session的區別

v$session.CREATOR_ADDR列的使用

⑤ 對inactive會話的處理(1sqlnet.ora檔案中設定expire_time 引數 2、使用者profileidle_time 引數 3、找到很久沒有響應的會話然後kill)

v$session.LAST_CALL_ET的使用

PMON的清理週期隱含引數"_PKT_PMON_INTERVAL"介紹

 

  Tips:

① 本文在ITpubhttp://blog.itpub.net/26736162)和部落格園(http://www.cnblogs.com/lhrbest)有同步更新

② 文章中用到的所有程式碼,相關軟體,相關資料,MOS資料請前往小麥苗的雲盤下載(http://blog.itpub.net/26736162/viewspace-1624453/

若文章程式碼格式有錯亂,推薦使用搜狗360QQ瀏覽器,也可以下載pdf格式的文件來檢視,pdf文件下載地址:http://blog.itpub.net/26736162/viewspace-1624453/

本篇BLOG中命令的輸出部分需要特別關注的地方我都用灰色背景和粉紅色字型來表示,比如下邊的例子中,thread 1的最大歸檔日誌號為33thread 2的最大歸檔日誌號為43是需要特別關注的地方;而命令一般使用黃色背景和紅色字型注;對程式碼或程式碼輸出部分的注釋一般採用藍色字型表示

 

  List of Archived Logs in backup set 11

  Thrd Seq     Low SCN    Low Time            Next SCN   Next Time

  ---- ------- ---------- ------------------- ---------- ---------

  1    32      1621589    2015-05-29 11:09:52 1625242    2015-05-29 11:15:48

  1    33      1625242    2015-05-29 11:15:48 1625293    2015-05-29 11:15:58

  2    42      1613951    2015-05-29 10:41:18 1625245    2015-05-29 11:15:49

  2    43      1625245    2015-05-29 11:15:49 1625253    2015-05-29 11:15:53

 

 

 

 

[ZHLHRDB1:root]:/>lsvg -o

T_XDESK_APP1_vg

rootvg

[ZHLHRDB1:root]:/>

00:27:22 SQL> alter tablespace idxtbs read write;

 

 

====》2097152*512/1024/1024/1024=1G 

 

 

 

本文如有錯誤或不完善的地方請大家多多指正,ITPUB留言或QQ皆可,您的批評指正是我寫作的最大動力。

 

 

1.2.2  相關參考文章連結

 

disconnect sessionkill session的區別:http://blog.itpub.net/26736162/viewspace-1979223/

1.2.3  本文簡介

今天同事殺會話的時候採用了alter system kill session xxx,xxx的方式,結果殺完後,v$session中還可以查到,就求助我,因為我之前殺會話都是帶的immediate的,殺完後會立刻釋放,v$session中也查詢不到,同事現在的情況就只能殺後臺程式了,但paddr列關聯不到後臺程式,查了下MOS還是給出了一些辦法,整理了一下,分享給大家。

 

1.3  相關知識點掃盲(摘自網路+個人總結)

1.3.1  得到當前會話的幾個SQL

SELECT USERENV('SID') FROM DUAL;

SELECT SID FROM V$MYSTAT WHERE ROWNUM =1;

 

SELECT b.SID,

       b.SERIAL#

FROM   v$session b

WHERE  b.SID = USERENV('SID');

 

SELECT a.SID,

       b.SERIAL#

FROM   v$mystat  a,

       v$session b

WHERE  a.SID = b.SID

AND    rownum = 1;

 

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=???;

 

 

1.3.2  Session 狀態說明

Oracle session 有如下幾種狀態:

ACTIVE - Session currently executing SQL

INACTIVE

KILLED - Session marked to be killed

CACHED - Session temporarily cached for use by Oracle*XA

SNIPED - Session inactive, waiting on the client

 

 

有關狀態的說明:

(1active 處於此狀態的會話,表示正在執行,處於活動狀態。

官方文件說明:

Any session that is connected to the database and is waiting for an event that does not belong to the Idle wait class is considered as an active session.

 

(2killed處於此狀態的會話,被標註為刪除,表示出現了錯誤,正在回滾。

當然,也是佔用系統資源的。還有一點就是,killed的狀態一般會持續較長時間,而且用windows下的工具pl/sql developerkill掉,是不管用的,要用命令:alter system kill session 'sid,serial#' ;

 

(3inactive 處於此狀態的會話表示不是正在執行的

該狀態處於等待操作(即等待需要執行的SQL語句),通常當DML語句已經完成。 但連線沒有釋放,這個可能是程式中沒有釋放,如果是使用中介軟體來連線的話,也可能是中介軟體的配置或者是bug 導致。inactive對資料庫本身沒有什麼影響,但是如果程式沒有及時commit,那麼就會造成佔用過多會話。容易是DB session 達到極限值。

一般不處理inactive 狀態的session, 如果達到了session 的最大值, 就增加processes sessions 引數。 對於Inactive 狀態的session,可以設定過期時間:

(1sqlnet.ora檔案中設定expire_time 引數

(2設定使用者profileidle_time 引數

3)找到很久沒有響應的會話然後kill

 

當設定了resource_limit=true 。通過idle_time限制session idle 時間。session idle超過設定時間,狀態為sniped (v$session).,然而OS下的process並不會釋放,當session(user process) 再次與server process 通訊,將關閉相應的server process.

sqlnet.expire_time 的原理不一樣,Oracle Server 傳送包探測dead connection ,如果連線關閉,或者不再用,則關閉相應的server process.

以上兩者組合使用,減少server process,防止process超過init$ORACLE_SID極限值。

 

本文會對這3種方式分別說明的。

 

1.3.2.1  清理inactive會話的3種方式

一、 設定sqlnet.expire_time

可以在sqlnet.ora檔案裡面加上sqlnet.expire_time這個引數來解決,設定一個分鐘數,這是ORACLE建議的DCD解決方法

在 sqlnet.ora檔案中設定expire_time 引數

官網有關這個引數的說明:

http://download.oracle.com/docs/cd/B19306_01/network.102/b14213/sqlnet.htm

Oracle? Database Net Services Reference 11g Release 2 (11.2)E10835-10

 

SQLNET.EXPIRE_TIME

Purpose

Use parameter SQLNET.EXPIRE_TIME to specify a the time interval, in minutes, to send a probe to verify that client/server connections are active. Setting a value greater than 0 ensures that connections are not left open indefinitely, due to an abnormal client termination. If the probe finds a terminated connection, or a connection that is no longer in use, it returns an error, causing the server process to exit. This parameter is primarily intended for the database server, which typically handles multiple connections at any one time.

sqlnet.expire_time 的原理:Oracle Server 傳送包探測dead connection ,如果連線關閉,或者不再用,則關閉相應的server process.

 

Limitations on using this terminated connection detection feature are:

(1It is not allowed on bequeathed connections.

(2Though very small, a probe packet generates additional traffic that may downgrade network performance.

(3Depending on which operating system is in use, the server may need to perform additional processing to distinguish the connection probing event from other events that occur. This can also result in degraded network performance.

 

Default 0

Minimum Value 0

Recommended Value 10

 

Example

SQLNET.EXPIRE_TIME=10

 

 

二、 設定使用者profileidle_time 引數

          

Oracle 使用者 profile 屬性

   http://blog.csdn.net/tianlesoftware/archive/2011/03/10/6238279.aspx

 

注意,要啟用idle_time 要先啟用RESOURCE_LIMIT引數。 該引數預設是False。 官網說明如下:

 RESOURCE_LIMIT

Property

Description

Parameter type

Boolean

Default value

false

Modifiable

ALTER SYSTEM

Range of values

true | false

 

RESOURCE_LIMIT determines whether resource limits are enforced in database profiles.

Values:

TRUEEnables the enforcement of resource limits

FALSEDisables the enforcement of resource limits

 

三、 找到很久沒有響應的會話然後kill

關於v$sessionLAST_CALL_ET列的理解:http://blog.itpub.net/26736162/viewspace-1762403/

 

根據v$sessionLAST_CALL_ET列的意義我們可以寫出如下的SQL指令碼,沒一個小時清理10個小時沒有響應的會話:

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個小時之前的會話 ,告警日誌中會記錄被殺掉的會話資訊

        -----------------------------------------------------------------------------------

 

    BEGIN

 

        -- 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';

SQL> col JOB_ACTION format a20
SQL>  SELECT d.job_name,d.job_action,d.run_count FROM dba_scheduler_jobs d WHERE d.job_name='JOB_P_KILL_SESSION_LHR';

JOB_NAME                       JOB_ACTION            RUN_COUNT
------------------------------ -------------------- ----------
JOB_P_KILL_SESSION_LHR         P_kill_session_LHR            4



 

執行日誌:

SELECT * FROM dba_scheduler_job_run_details  d WHERE d.job_name='JOB_P_KILL_SESSION_LHR';

wpsFB04.tmp 

 

1.3.3  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.

 

1.3.4  kill session相關內容

kill session DBA到的事情之一。如果kill 掉了不kill session具有破壞性,因此可能的避免這樣錯誤發生。同應當注意,如果kill session於Oracle 後臺程,容易庫實例當機。

一、得需要kill session的資訊

 

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 來確認。

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將導致需要killsession不能立即掉。這種況將收到 "marked for kill"提示(如下),一旦會話當前事或操作完成,該會話被立即掉。

    alter system kill session '4730,39171'

    *

    ERROR at line 1:

    ORA-00031: session marked for kill

  在下面的操作中將殺會話146144

    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地址生了化,查詢結果中的色字型。如果多sessionkill 掉,sessionPADDR被改相同的程地址被殺掉的會話的server列變為PSEUDO

1.3.4.1  oracle killed會話不釋放的問題

 

一般情況下,在殺一個會話的時候,直接執行alter system kill session ‘sid,serial#’;

Administrator's Guide說,當sessionactive的時候,alter system kill session 只是將session的狀態標識為killedserver變為pseudo狀態,並不會釋放session持有的資源,所以我們在執行完alter system kill session 後,看會話還是一直存在。

這種情況下可以使用 immediate選項,強制立即Kill會話,如下:

SQL> alter system kill session '3964,51752' immediate;

  SQL Language Referencehttp://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.

1.3.4.2  killed狀態的會話如何找到spid

一般情況下我們查詢會話的後臺程式是通過如下的SQL,即通過v$sessionpaddr列關聯v$processaddr列,但是killed狀態的v$sessionpaddr列都變成了一樣的,所以已經沒有辦法通過如下的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$sesionkilled狀態那麼我們通過上面的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 我自己常用的方法

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 

 

1.3.4.3  為何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後,會話狀態變為killedpmon回收資源後,會話的資訊仍然保留在v$session中,直到客戶端再次請求,資料庫返回ORA-28錯誤:"your session has been killed"

此時pmon才從v$session中移除這些會話的資訊。而上述中,客戶端機器重啟,無法再向資料庫傳送請求,因此從v$session中一直可以查到,只有通過作業系統強制殺掉程式,才能觸發pmonv$session中清除。

然後Oracle就等待PMON去清除這些Session.所以通常等待一個被標記為KilledSession退出需要花費很長的時間.如果此時被Killprocess,重新嘗試執行任務,那麼馬上會收到程式中斷的提示,process退出,此時Oracle會立即啟動PMON來清除該session.這被作為一次異常中斷處理.

1.3.4.4  為何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_ADDRCREATOR_SERIAL#用於標記這種情況。然後就可以通過作業系統命令kill -9來殺掉這些程式了。

 

1.3.4.5  ALTER SYSTEM KILL SESSION 許可權不足

需要賦許可權,dba角色不用,grant alter system to lhr;

 

 

 

 

 

1.1.1.1  授予普通使用者殺自己session的許可權

若沒有dba角色或者沒有alter system許可權的話,業務使用者就不能自己殺自己會話了,這樣一來,只能dba來介入了,其實這個功能我們可以通過如下的SQL指令碼來完成。

-------  user replace XXXXXX

-------   普通使用者可以kill自己的session 授予應用使用者殺自己session的許可權

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);

 

1.1.1.2  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 錯程式的機率。

 

1.1.1.3  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;

 

1.1.1  MOS上的一些資料

wpsE3B2.tmpwpsE3B3.tmpwpsE3B4.tmp

wpsE3B5.tmp

wpsE3B6.tmpwpsE3B7.tmpwpsE3C8.tmpwpsE3C9.tmp

wpsE3CA.tmpwpsE3CB.tmpwpsE3CC.tmpwpsE3CD.tmp

於是metalinkgoogle到以下一些資料:

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

 

 

 

---------------------------------------------------------------------------------------------------------------------

 

 

第二章 實驗部分

二.1  實驗環境介紹

專案

primary db

db 型別

單例項

db version

11.2.0.3.0

db 儲存

ASM

主機IP地址/hosts配置

192.168.59.129

OS版本及kernel版本

rhel 6.5

 

 

二.2  實驗內容

實驗序號

實驗內容

1

設定使用者profileidle_time 引數

2

kill session的時候加immediate和不加的區別

3

授予普通使用者kill自己使用者的許可權

4

KILLED狀態的會話如何找到相關的SPID

 

 

二.3  實驗過程

 

二.3.1  設定使用者profileidle_time 引數

可以參考:

http://blog.csdn.net/leshami/article/details/9184917

http://blog.csdn.net/tianlesoftware/article/details/6238279

 

設定resource_limit true,該引數預設為false

[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:\Users\xiaomaimiao>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>

 

 

二.3.2  授予普通使用者殺自己session的許可權

 

建立普通使用者lhrtest,授予resource和connect許可權。

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:\Users\xiaomaimiao>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>

 

可以看到普通使用者也可以殺掉自己使用者的會話了。

 

 

二.3.3  kill session的時候加immediate和不加immediate的區別

 

kill session 的測試:

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;

 

[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檢視也被清理了。

 

---------------------------------------------------------------------------------------------------------------------

今天編寫的兩條極具殺傷力的命令,它可以瞬間將Oracle殺死在無形之中。後面我將給出簡單註釋並展示一下它的威力。
$ ps -ef |grep $ORACLE_SID|grep -v grep|awk '{print $2}' | xargs kill -9
$ ipcs -m | grep oracle | awk '{print $2}' | xargs ipcrm shm

這兩條命令的來由:
今天處理了三起Oracle資料庫無故無法登入的問題,無論你採取什麼手段都無法登陸到Oracle的SQL*PLus中,更談不上故障排查了。
這種情況下有兩種選擇,第一種選擇是經過一個較長的時間來排查故障原因,另外一種方法是不惜一切代價啟動資料庫以便儘快恢復生產。

如果是測試實驗環境可以使用第一種方法來完成,對於排查問題的經驗積累是有意的。
如果是生產環境,減少停機時間是最最至上的原則,所以我們只有不惜一切代價讓資料庫儘快恢復使用。

對於儘快恢復生產的方法主要也有兩種。
第一種不惜代價的方法是重啟伺服器主機,徹底釋放一切資源,重新來過,這種方法是有效的,不過停機時間還是有點長,而且技術含量比較低,所以不是很推薦使用這種超級“簡單粗暴”的方法。
第二種方法就是我將要給大家展示的方法。

1.第一步:使用Linux的kill命令殺死所有與oracle有關的程式。
1)查詢到與ORACLE_SID相關的oracle程式
$ ps -ef |grep $ORACLE_SID
oracle    7776     1  0 22:51 ?        00:00:00 ora_pmon_ora10g
oracle    7778     1  0 22:51 ?        00:00:00 ora_psp0_ora10g
oracle    7780     1  0 22:51 ?        00:00:00 ora_mman_ora10g
oracle    7782     1  0 22:51 ?        00:00:00 ora_dbw0_ora10g
oracle    7784     1  0 22:51 ?        00:00:00 ora_dbw1_ora10g
oracle    7786     1  0 22:51 ?        00:00:00 ora_lgwr_ora10g
oracle    7788     1  0 22:51 ?        00:00:00 ora_ckpt_ora10g
oracle    7790     1  0 22:51 ?        00:00:00 ora_smon_ora10g
oracle    7792     1  0 22:51 ?        00:00:00 ora_reco_ora10g
oracle    7794     1  0 22:51 ?        00:00:00 ora_cjq0_ora10g
oracle    7796     1  0 22:51 ?        00:00:00 ora_mmon_ora10g
oracle    7798     1  0 22:51 ?        00:00:00 ora_mmnl_ora10g
oracle    7832     1  0 22:51 ?        00:00:00 ora_arc0_ora10g
oracle    7834     1  0 22:51 ?        00:00:00 ora_arc1_ora10g
oracle    7836     1  0 22:51 ?        00:00:00 ora_qmnc_ora10g
oracle    7842     1  0 22:51 ?        00:00:00 ora_q000_ora10g
oracle    7847     1  0 22:52 ?        00:00:00 ora_q001_ora10g
oracle    7951  7592  0 23:11 pts/2    00:00:00 grep ora10g

2)去除掉包含grep命令本身的記錄
$ ps -ef |grep $ORACLE_SID |grep -v grep
oracle    7776     1  0 22:51 ?        00:00:00 ora_pmon_ora10g
oracle    7778     1  0 22:51 ?        00:00:00 ora_psp0_ora10g
oracle    7780     1  0 22:51 ?        00:00:00 ora_mman_ora10g
oracle    7782     1  0 22:51 ?        00:00:00 ora_dbw0_ora10g
oracle    7784     1  0 22:51 ?        00:00:00 ora_dbw1_ora10g
oracle    7786     1  0 22:51 ?        00:00:00 ora_lgwr_ora10g
oracle    7788     1  0 22:51 ?        00:00:00 ora_ckpt_ora10g
oracle    7790     1  0 22:51 ?        00:00:00 ora_smon_ora10g
oracle    7792     1  0 22:51 ?        00:00:00 ora_reco_ora10g
oracle    7794     1  0 22:51 ?        00:00:00 ora_cjq0_ora10g
oracle    7796     1  0 22:51 ?        00:00:00 ora_mmon_ora10g
oracle    7798     1  0 22:51 ?        00:00:00 ora_mmnl_ora10g
oracle    7832     1  0 22:51 ?        00:00:00 ora_arc0_ora10g
oracle    7834     1  0 22:51 ?        00:00:00 ora_arc1_ora10g
oracle    7836     1  0 22:51 ?        00:00:00 ora_qmnc_ora10g
oracle    7842     1  0 22:51 ?        00:00:00 ora_q000_ora10g
oracle    7847     1  0 22:52 ?        00:00:00 ora_q001_ora10g

3)使用awk命令得到我們關心的程式號
$ ps -ef |grep $ORACLE_SID |grep -v grep|awk '{print $2}'
7776
7778
7780
7782
7784
7786
7788
7790
7792
7794
7796
7798
7832
7834
7836
7842
7847

4)萬事俱備,我們最後使用kill命令將oracle的程式殺死,因此得到了下面完整的命令
$ ps -ef |grep $ORACLE_SID |grep -v grep|awk '{print $2}' | xargs kill -9

2.第二步:使用Linux的ipcs和ipcsrm命令釋放oracle佔用的共享記憶體。
1)使用ipcs命令檢視系統中共享記憶體使用情況
$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 32768      root      644        72         2          dest
0x00000000 65537      root      644        16384      2          dest
0x00000000 98306      root      644        280        2          dest
0x00000000 131075     root      644        790528     2          dest
0x00000000 163844     root      644        790528     2          dest
0x00000000 196613     root      644        790528     2          dest
0x00000000 327689     oracle    644        790528     2          dest
0x00000000 360458     oracle    644        790528     2          dest
0x00000000 393227     oracle    644        790528     2          dest
0xecc5fba0 786447     oracle    640        5370806272 30

2)使用grep命令過濾後得到與oracle相關的內容
$ ipcs -m | grep oracle
0x00000000 327689     oracle    644        790528     2          dest
0x00000000 360458     oracle    644        790528     2          dest
0x00000000 393227     oracle    644        790528     2          dest
0xecc5fba0 786447     oracle    640        5370806272 31

2)使用awk命令獲得上面我們關心的shmid欄位內容
$ $ ipcs -m | grep oracle | awk '{print $2}'
327689
360458
393227
786447

3)最後使用ipcsrm命令釋放共享記憶體
$ ipcs -m | grep oracle | awk '{print $2}' | xargs ipcrm shm
resource(s) deleted

再次檢視一下,此時共享記憶體已經被釋放。
$ ipcs -m | grep oracle
0x00000000 327689     oracle    644        790528     2          dest
0x00000000 360458     oracle    644        790528     2          dest
0x00000000 393227     oracle    644        790528     2          dest
0x00000000 786447     oracle    640        5370806272 31         dest

3.此時,我們便可以登入到資料庫,最後啟動資料庫恢復生產。

4.小結
這種方法相對也是比較“粗暴”的。不過在危難之時還是可以派上用場。
重點強調:
手工殺掉oracle程式和手工釋放共享記憶體是非常危險的,不到萬不得已,千萬不要使用;
這裡我給出的兩條極具殺傷力的命令,請不要輕易嘗試。

Good luck.

-- The End --



disconnect session和kill session的區別 

最常用的殺死oracle程式的方法是alter system kill session ‘sid,serial#’。

但是今天遇到一些意外,資料庫有個從6月12號執行至今的sql,經客戶確認需要將其幹掉,登陸資料庫執行alter system kill。

於是有了以下情形

SQL> alter system kill session '137,7818';

alter system kill session '137,7818'

*

ERROR at line 1:

ORA-00031: session marked for kill

 

SQL> select status,event from v$session where sid = 137;

STATUS   EVENT

-------- ----------------------------------------------------------------

KILLED   SQL*Net more data from dblink

 

SQL>  select object_id,locked_mode,session_id from v$locked_object;

OBJECT_ID LOCKED_MODE SESSION_ID

---------- ----------- ----------

       165           3        137

    104489           3        137

       212           3        137

 

SQL> select TYPE,LMODE,REQUEST,BLOCK from v$lock where sid=137;

TY      LMODE    REQUEST      BLOCK

-- ---------- ---------- ----------

JQ          6          0          0

JI          6          0          0

TM          3          0          0

TM          3          0          0

TM          3          0          0

TX          6          0          0

 

SQL> select t.status, s.status from v$transaction t, v$session s where s.taddr = t.addr and s.sid=137;

STATUS           STATUS

---------------- --------

ACTIVE           KILLED

 

該session已經被標誌為killed,但是其對應的transaction依舊為active,且對應的lock沒有被釋放;

又因為該instance由其他OS使用者啟動,當前登入的使用者沒有許可權執行kill -9

ora_10@justin_$ ps -ef | grep 15616

ora_xxx 15616     1  0   Jul 06 ?        0:22 ora_j001_GLIMSP

ora_10  20035 17648  0 08:23:18 pts/7    0:00 grep 15616

ora_10@justin_$ kill -9 15616

kill: 15616: permission denied

 

不是太清楚到底發生了什麼事情,但此時可使用disconnect session,請參考以下解釋

The KILL SESSION command doesn’t actually kill the session. It merely asks the session to kill itself. In some situations, like waiting for a reply from a remote database or rolling back transactions, the session will not kill itself immediately and will wait for the current operation to complete. In these cases the session will have a status of “marked for kill”. It will then be killed as soon as possible.

The ALTER SYSTEM DISCONNECT SESSION syntax as an alternative method for killing Oracle sessions. Unlike the KILL SESSION command which asks the session to kill itself, the DISCONNECT SESSION command kills the dedicated server process (or virtual circuit when using Shared Sever), which is equivalent to killing the server process from the operating system. The basic syntax is similar to the KILL SESSION command with the addition of the POST_TRANSACTION clause. The SID and SERIAL# values of the relevant session can be substituted into one of the following statements.

The POST_TRANSACTION clause waits for ongoing transactions to complete before disconnecting the session, while the IMMEDIATE clause disconnects the session and ongoing transactions are recovered immediately.

http://fatihacar.com/blog/show-and-kill-transaction-lock-in-oracle/

SQL> alter system disconnect session '137,7818' immediate;

 

System altered.

 

SQL> select serial#,status,event from v$session where sid=137;

 

   SERIAL# STATUS

---------- --------

EVENT

----------------------------------------------------------------

      7822 ACTIVE

jobq slave wait

 

 

SQL> alter system disconnect session '137,7822' immediate;

 

System altered.

 

SQL> select serial#,status,event from v$session where sid=137;

 

no rows selected

 

SQL> select object_id,locked_mode,session_id from v$locked_object;

 

 OBJECT_ID LOCKED_MODE SESSION_ID

---------- ----------- ----------

       165           3        132

    104489           3        132

       212           3        132

 

SQL> select serial#,event,status,sql_id from v$session where sid=132;

 

   SERIAL# EVENT

---------- ----------------------------------------------------------------

STATUS   SQL_ID

-------- -------------

     24231 jobq slave wait

ACTIVE

 

 

SQL> alter system disconnect session '132,24231' immediate;

 

System altered.

 

SQL> select object_id,locked_mode,session_id from v$locked_object;

 

no rows selected

 

--此時session被徹底清除,對應的lock也已釋放



About Me

...............................................................................................................................

● 本文作者:小麥苗,只專注於資料庫的技術,更注重技術的運用

● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/viewspace-2121019/

● 本文部落格園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 聯絡我請加QQ好友(646634621),註明新增緣由

● 於 2016-06-15 10:00~ 2016-06-26 19:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

...............................................................................................................................

拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。

Oracle kill session相關問題(上)
DBA筆試面試講解
歡迎與我聯絡

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22207394/viewspace-2121114/,如需轉載,請註明出處,否則將追究法律責任。

相關文章