最近系統連續出現好幾次鎖表,昨晚又發生一次鎖表,11點鍾跑到客戶現場,進過跟蹤發現導致這次鎖表的機器和上一次是同一台,花了近半小時解鎖。之后到科室找到那台機器看看情況,發現那台機器速度超慢,保存一份病歷需要幾十秒鍾,原因應該就在這里了。
分析原因:保存病歷時發生超時,Nhibernate在發生超時時事務需要進行回滾,但是回滾的時候也發生了異常,沒有回滾成功,導致了鎖表。
處理方法:a、先解決該機器速度慢的問題,配置太差的機器要求醫院進行硬件升級;b、驗證事務回滾的時候是否有可能發生回滾異常。
先貼出現場處理死鎖的步驟。
另外:有時候通過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'--加上用戶名是避免把其他系統的會話也關閉,以免傷及無辜
)
2、批量執行第一步生成的語句
alter system kill session 'sid,serial#';
--alter system kill session '6976,33967';
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 = 6 --session_id
and s.paddr = p.addr;
*/
4、查詢是執行何sql語句導致鎖表的
select b.sql_text
from v$session a, v$sql b
where a.sid = 6 --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#;
*/