1、找到sid,serial#;
SELECT /*+ rule */ s.username, l.type,
decode(l.type,'TM','TABLE LOCK',
'TX','ROW LOCK',
NULL) LOCK_LEVEL,
o.owner,o.object_name,o.object_type,
s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser,s.status
FROM v$session s,v$lock l,dba_objects o
WHERE l.sid = s.sid
AND l.id1 = o.object_id(+)
AND s.username is NOT NULL order by l.type;
2、根據找到的sid,serial#,執行以下語句,清除進程。
alter system kill session '~sid~,~serial#~';
例如: alter system kill session '14,4820';
如果死鎖不能自動釋放,就需要我們手工的kill session。 步驟如下:
1. 查看有無死鎖對象,如有kill session
SELECT 'alter system kill session ''' || sid || ',' || serial# || ''';' "Deadlock"
FROM v$session
WHERE sid IN (SELECT sid
FROM v$lock
WHERE block = 1);
如果有,會返回類似與如下的信息:
alter system kill session '132,731';
alter system kill session '275,15205';
alter system kill session '308,206';
alter system kill session '407,3510';
kill session:
執行alter system kill session '391,48398'(sid為391);
注意:應當注意對于sid在100以下的應當謹慎,可能該進程對應某個application,如對應某個事務,可以kill.
2. 查看導致死鎖的SQL
SELECT s.sid, q.sql_text
FROM v$sqltext q, v$session s
WHERE q.address = s.sql_address AND s.sid = &sid -- 這個&sid 是第一步查詢出來的
ORDER BY piece;
返回:
SID SQL_TEXT
---------- ----------------------------------------------------------------
77 UPDATE PROFILE_USER SET ID=1,COMPANY_ID=2,CUSTOMER_ID=3,NAMED
77 _INSURED_ID=4,LOGIN=5,ROLE_ID=6,PASSWORD=7,EMAIL=8,TIME_ZON
77 E=9 WHERE PROFILE_USER.ID=:34
3 rows selected.
3. 查看誰鎖了誰
SELECT s1.username
|| '@'
|| s1.machine
|| ' ( SID='
|| s1.sid
|| ' ) is blocking '
|| s2.username
|| '@'
|| s2.machine
|| ' ( SID='
|| s2.sid
|| ' ) '
AS blocking_status
FROM v$lock l1,
v$session s1,
v$lock l2,
v$session s2
WHERE s1.sid = l1.sid
AND s2.sid = l2.sid
AND l1.BLOCK = 1
AND l2.request > 0
AND l1.id1 = l2.id1
AND l2.id2 = l2.id2;
或者
SELECT
LPAD (' ', DECODE (l.xidusn, 0, 3, 0))
|| l.oracle_username
User_name,
o.owner,
o.object_name,
o.object_type,
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
ORDER BY o.object_id, xidusn DESC
三.鎖 和 阻塞
3.1 相關概念
通常來講,系統如果平時運行正常,突然會停止不動,多半是被阻塞(Blocked)住了。 我們可以通過v$lock 這張視圖,看查看阻塞的信息。
SQL> desc v$lock;
名稱 是否為空? 類型
----------------------------------------- -------- -----------------
ADDR RAW(4)
KADDR RAW(4)
SID NUMBER
TYPE VARCHAR2(2)
ID1 NUMBER
ID2 NUMBER
LMODE NUMBER
REQUEST NUMBER
CTIME NUMBER
BLOCK NUMBER
我們關注的比較多的是request 和 block 字段。
如果某個request列是一個非0值,那么它就是在等待一個鎖。 如果block列是1,這個SID 就持有了一個鎖,并且阻塞別人獲得這個鎖。 這個鎖的類型由TYPE 字段定義。鎖的模式有LMODE 字段定義,ID1和ID2 字段定義了這個鎖的相關信息。ID1相同,就代表指向同一個資源。這樣就有可能有加鎖者和等待者。 LMODE 的6中模式參考上面的TM鎖類型表。
可以結合v$lock 和 v$session 視圖來查詢相關的信息:
SELECT sn.username,
m.SID,
sn.SERIAL#,
m.TYPE,
DECODE (m.lmode,
0,
'None',
1,
'Null',
2,
'Row Share',
3,
'Row Excl.',
4,
'Share',
5,
'S/Row Excl.',
6,
'Exclusive',
lmode,
LTRIM (TO_CHAR (lmode, '990')))
lmode,
DECODE (m.request,
0,
'None',
1,
'Null',
2,
'Row Share',
3,
'Row Excl.',
4,
'Share',
5,
'S/Row Excl.',
6,
'Exclusive',
request,
LTRIM (TO_CHAR (m.request, '990')))
request,
m.id1,
m.id2
FROM v$session sn, v$lock m
WHERE (sn.SID = m.SID AND m.request != 0) --存在鎖請求,即被阻塞
OR (sn.SID = m.SID --不存在鎖請求,但是鎖定的對象被其他會話請求鎖定
AND m.request = 0 AND lmode != 4
AND (id1, id2) IN
(SELECT s.id1, s.id2
FROM v$lock s
WHERE request != 0
AND s.id1 = m.id1
AND s.id2 = m.id2))
ORDER BY id1, id2, m.request;
或者
SELECT
s .username,
DECODE (l.TYPE, 'TM', 'TABLE LOCK', 'TX', 'ROW LOCK', NULL)
LOCK_LEVEL,
o.owner,
o.object_name,
o.object_type,
s.sid,
s.serial#,
s.terminal,
s.machine,
s.program,
s.osuser
FROM v$session s, v$lock l, dba_objects o
WHERE l.sid = s.sid AND l.id1 = o.object_id(+) AND s.username IS NOT NULL