Oracle 鎖的原因及解決辦法

原因

產生的原因最大的可能就是更改數據沒有提交事務,數據庫就將表鎖住!所以在更新時不要用select * from a for update這樣的語句很容易鎖表,可能用select *,t.rowid from t 這樣的語句代替,這個也是數據庫推薦使用的語句。

處理辦法:

最近系統連續出現好幾次鎖表,昨晚又發生一次鎖表,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#;

*/


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