oracle中鎖的問題--在OS一級殺掉oracle殺不掉的進程--查殺鎖表進程

前兩天同事又碰到oracle連接n慢的問題,由於這個現象時有時無,於是我檢查了下是不是表或者其他對象有被鎖住,或者是否有死鎖。對象資源被鎖是一個經常要碰到的急需解決的問題。

 

在Oracle裏,當前的鎖的信息存儲在動態性能視圖v$lock和v$locked_object中。先來看下它們定義:

 

Oracle官方文檔及簡單翻譯 (oracle官方可下載資源網址在我的收藏裏有列出):

V$LOCK V$LOCKED_OBJECTV$LOCKED_OBJECT lists all locks acquired by every transaction on the system. It shows which sessions are holding DML locks (that is, TM-type enqueues) on what objects and in what mode.

V$LOCK lists the locks currently held by the Oracle Database and outstanding requests for a lock or latch.

視圖V$LOCK列出了當前被Oracle數據庫持有的所有的鎖以及未完成的鎖和栓鎖請求。

Column Datatype Description
ADDR RAW(4 | 8) Address of lock state object/內存中被鎖的對象的地址
KADDR RAW(4 | 8) Address of lock/內存中鎖地址
SID NUMBER Identifier for session holding or acquiring the lock/持有或申請鎖的會話標識號
TYPE VARCHAR2(2) Type of user or system lock/系統鎖或者用戶鎖類型

The locks on the user types are obtained by user applications. Any process that is blocking others is likely to be holding one of these locks. The user type locks are:

TM - DML enqueue/表級鎖或DML鎖

TX - Transaction enqueue/行級鎖或事務鎖

UL - User supplied/用戶鎖

The locks on the system types are held for extremely short periods of time. The system type locks are listed in Table 8-1 .

 

ID1 NUMBER

Lock identifier #1 (depends on type)

鎖的第1標識號

如果鎖的類型是TM,該值表示將要被鎖定的對象的標識號;

如果鎖的類型是TX,該值表示撤銷段號碼的十進制值

ID2 NUMBER

Lock identifier #2 (depends on type)

鎖的第2標識號。

如果鎖的類型是TM,該值爲0;

如果鎖的類型是TX,該值表示交換次數

LMODE NUMBER

Lock mode in which the session holds the lock:

會話保持的鎖的模式

  • 0 - none

  • 1 - null (NULL) 空

  • 2 - row-S (SS) 行共用(RS):共用表鎖,sub share

  • 3 - row-X (SX)  行獨佔(RX):用於行的修改,sub exclusive

  • 4 - share (S) 共用鎖(S):阻止其他DML操作,share

  • 5 - S/Row-X (SSX) 共用行獨佔(SRX):阻止其他事務操作,share/sub exclusive

  • 6 - exclusive (X) 獨佔(X):獨立訪問使用,exclusive

鎖的級別越高影響的操作越多。
REQUEST NUMBER

Lock mode in which the process requests the lock:

會話申請的鎖的模式。與LMODE中的模式相同

  • 0 - none

  • 1 - null (NULL)

  • 2 - row-S (SS)

  • 3 - row-X (SX)

  • 4 - share (S)

  • 5 - S/Row-X (SSX)

  • 6 - exclusive (X)

CTIME NUMBER

Time since current mode was granted

以秒爲單位的,獲得當前鎖(或轉換成當前鎖的模式)以來的時間

BLOCK NUMBER

A value of either 0 or 1, depending on whether or not the lock in question is the blocker.

當前鎖是否阻塞另一個鎖。0=不阻塞;1=阻塞

 

視圖V$LOCKED_OBJECT列出系統中每個事務獲得的所有鎖。它列出了那些以具體哪些模式對具體哪些對象持有TM鎖的會話。

Column Datatype Description
XIDUSN NUMBER Undo segment number/撤銷段號碼
XIDSLOT NUMBER Slot number/被鎖定的對象在撤銷段中的位置
XIDSQN NUMBER Sequence number/序列號
OBJECT_ID NUMBER Object ID being locked/被鎖定的對象的標識號
SESSION_ID NUMBER Session ID/ 會話的標識號
ORACLE_USERNAME VARCHAR2(30) Oracle user name/Oracle用戶名
OS_USER_NAME VARCHAR2(30) OS user name/操作系統用戶名
PROCESS VARCHAR2(12) OS process ID/操作系統進程標識號
LOCKED_MODE NUMBER Lock mode/

對象被鎖定的模式。

0=None;1=Null;2=Row-S (SS);3=Row-X (SX);

4=Share;5=S/Row-X (SSX);6=Exclusive

 

查找有關鎖/死鎖的更多我們需要的信息有時還需要通過表all_objects或者視圖v$session,它們就不再一一講解,請到oracle官方文檔 查詢。

 

查詢有關鎖的信息:

 

查詢一:

 select a.os_user_name,
         a.oracle_username,
          a.object_id,
          c.object_name,
       c.object_type
    from v$locked_object a, dba_objects c
    where a.object_id=c.object_id;

 

查詢二:

 

select s.PROCESS,
       s.SID,
       s.SERIAL#,
       b.object_name,
       b.subobject_name,
       a.LOCKED_MODE,
       s.OSUSER,
       s.LOGON_TIME,
       s.MACHINE,
       s.PROGRAM,
       s.SQL_ADDRESS,
       s.SQL_HASH_VALUE            
  from v$locked_object a, dba_objects b, v$session s
where a.OBJECT_ID = b.object_id
   and a.SESSION_ID = s.SID

 

找到鎖/死鎖就好辦了。找到相應需要解開的鎖可以通過完成該事務或者殺死會話解鎖。

 

殺鎖進程可以用以下命令:

alter system kill session ' '查出的SID,查出的SERIAL#'。(這個必須要用查詢二來獲得相關Session信息)

 

殺oracle會話進程有時會失效,需要根據SPID到系統中殺相應的oracle進程。另外要注意的是, 我看到網上有外國的學者說, 當直接連接數據庫時, 直接用OS命令 $kill process_num 或者 $kill -9 process_num殺系統進程來終止用戶連接也不能完全解決問題, 因爲一個用戶進程可能產生一個以上的鎖,殺oracle進程不能徹底解決鎖的問題。

 

Reference:

http://www.lslnet.com/linux/edosc/42/linux-42294950.htm

 

 

/////////////////

 

一些ORACLE中的進程被殺掉後,狀態被置爲"killed",但是鎖定的資源很長時間不釋放,有時實在沒辦法,只好重啓數據庫。現在提供一種方法解決這種問題,那就是在ORACLE中殺不掉的,在OS一級再殺。 

1.下面的語句用來查詢哪些對象被鎖: 

select object_name,machine,s.sid,s.serial# 
from v$locked_object l,dba_objects o ,v$session s 
where l.object_id = o.object_id and l.session_id=s.sid; 

2.下面的語句用來殺死一個進程: 
alter system kill session '24,111'; (其中24,111分別是上面查詢出的sid,serial#) 

【注】以上兩步,可以通過Oracle的管理控制檯來執行。 

3.如果利用上面的命令殺死一個進程後,進程狀態被置爲"killed",但是鎖定的資源很長時間沒有被釋放,那麼可以在os一級再殺死相應的進程(線程),首先執行下面的語句獲得進程(線程)號: 
select spid, osuser, s.program 
from v$session s,v$process p 
where s.paddr=p.addr and s.sid=24 (24是上面的sid) 

4.在OS上殺死這個進程(線程): 
1)在unix上,用root身份執行命令: 
#kill -9 12345(即第3步查詢出的spid) 
2)在windows(unix也適用)用orakill殺死線程,orakill是oracle提供的一個可執行命令,語法爲: 
orakill sid thread 
其中: 
sid:表示要殺死的進程屬於的實例名 
thread:是要殺掉的線程號,即第3步查詢出的spid。 
例:c:>orakill orcl 12345

 

 

/////////////

 

查看當前用戶的sid和serial#:

select sid, serial#, status from v$session where audsid=userenv('sessionid');

 

查看當前用戶的spid:

select spid from v$process p, v$session s where s.audsid=userenv('sessionid') and s.paddr=p.addr;

select spid from v$process p join v$session s on p.addr=s.paddr and s.audsid=userenv('sessionid');

 

查看當前用戶的trace file路徑:

select p.value || '/' || t.instance || '_ora_' || ltrim(to_char(p.spid,'fm99999')) || '.trc'

    from v$process p, v$session s, v$parameter p, v$thread t

    where p.addr = s.paddr and s.audsid = userenv('sessionid') and p.name = 'user_dump_dest';

 

已知spid,查看當前正在執行或最近一次執行的語句:

select /*+ ordered */ sql_text from v$sqltext sql

    where (sql.hash_value, sql.address) in (

        select decode(sql_hash_value, 0, prev_hash_value, sql_hash_value), decode(sql_hash_value, 0, prev_sql_addr, sql_address)

        from v$session s where s.paddr = (select addr from v$process p where p.spid = to_number('&pid')))

    order by piece asc;

 

查看鎖和等待:

col user_name format a10

col owner format a10

col object_name format a15

col sid format 999999

col serial# format 999999

col spid format a6

select /*+ rule */ lpad(' ', decode(l.xidusn, 0, 3, 0)) || l.oracle_username user_name,

    o.owner, o.object_name, o.object_type, s.sid, s.serial#, p.spid

    from v$locked_object l, dba_objects o, v$session s, v$process p

    where l.object_id = o.object_id and l.session_id = s.sid and s.paddr = p.addr

    order by o.object_id, xidusn desc;

 

///////////

 

查看鎖表進程SQL語句1: 
select sess.sid, 
    sess.serial#, 
    lo.oracle_username, 
    lo.os_user_name, 
    ao.object_name, 
    lo.locked_mode 
    from v$locked_object lo, 
    dba_objects ao, 
    v$session sess 
where ao.object_id = lo.object_id and lo.session_id = sess.sid; 

查看鎖表進程SQL語句2: 
select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID; 

殺掉鎖表進程: 
如有記錄則表示有lock,記錄下SID和serial# ,將記錄的ID替換下面的738,1429,即可解除LOCK 
alter system kill session '738,1429';


轉自:http://blog.csdn.net/thunder09/article/details/5418500

發佈了5 篇原創文章 · 獲贊 10 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章