最近系統每天經常鎖表,進程殺死后,很快再次鎖住這個表。
(一)先貼出現場處理死鎖的步驟。
另外:有時候通過PL/SQL執行kill session可能仍然無法解鎖,此時需要登陸到Oracle服務器將進程kill掉才行。
1、生成Kill Session語句
select 'alter system kill session ''' || SID ||',' || SERIAL# || ''';' from
(
select distinct a.sid, a.Serial#, status, machine, LOCKWAIT, logon_time
from v$session a, v$locked_object b
where (a.status = 'ACTIVE' or a.status = 'INACTIVE')
and a.sid = b.session_id
and b.ORACLE_USERNAME='XYHISTEST'--加上用戶名是避免把其他系統的會話也關閉,以免傷及無辜
);
或者
/*
select sess.sid,
sess.serial#,
lo.oracle_username,
lo.os_user_name,
ao.object_name,
lo.locked_mode,
sql.sql_text,
'alter system kill session ''' || SID ||',' || SERIAL# || ''';'
from v$locked_object lo,
dba_objects ao,
v$session sess,
v$sql sql
where ao.object_id = lo.object_id and lo.session_id = sess.sid and sql.ADDRESS(+)= sess.SQL_ADDRESS;
-- 這個sql查詢結果包含了sid, serial#,可以用來kill 被鎖死的session。
-- sql_text 字段可以知道導致死鎖的sql。
--最后一個字段是直接可以執行的殺死進程的sql語句。
*/
2、批量執行第一步生成的語句
alter system kill session 'sid,serial#';
--alter system kill session '3656,755';
3、查詢oracle用戶名,機器名,鎖表對象
SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username,
l.os_user_name,s.machine, s.terminal, o.object_name, s.logon_time
FROM v$locked_object l, all_objects o, v$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid
ORDER BY sid, s.serial# ;
/*或者
select s.SID, s.OSUSER, p.spid as OSPID, s.MACHINE, s.TERMINAL, s.PROGRAM
from v$session s, v$process p
where s.sid = 5864--session_id
and s.paddr = p.addr;
*/
4、查詢是執行何sql語句導致鎖表的
select b.sql_text
from v$session a, v$sql b
where a.sid =589 --session_id
and a.SQL_ADDRESS = b.ADDRESS(+);
/*--或者
SELECT l.session_id sid, s.serial#, l.locked_mode, l.oracle_username, s.user#,
l.os_user_name,s.machine, s.terminal,a.sql_text, a.action
FROM v$sqlarea a,v$session s, v$locked_object l
WHERE l.session_id = s.sid
AND s.prev_sql_addr = a.address
ORDER BY sid, s.serial#;
*/