記一次Oracle死鎖/阻塞排查

weixin_34041003發表於2019-01-15

1. 檢查資料庫確定 是否 真實存在死鎖,若有 哪臺機器哪個程式。

select username, lockwait, status, machine, program
from v$session
where sid in (select session_id from v$locked_object);

--Username:死鎖語句所用的資料庫使用者;
--Lockwait   :死鎖的狀態,如果有內容表示被死鎖。
--Status       :狀態,active表示被死鎖
--Machine   :死鎖語句所在的機器。
--Program   :產生死鎖的語句主要來自哪個應用程式。

2. 確定死鎖後,還可以檢查是哪個語句產生死鎖等待。

select sql_text
from v$sql
where hash_value in
      (select sql_hash_value from v$session where sid in (select session_id from v$locked_object));

3. 查詢未提交事務的SQL,大概率是其引起。

select s.sid,
       s.username,
       s.osuser,
       s.program,
       to_char(s.LOGON_TIME, 'yyyymmdd hh24:mi:ss')       as LOGON_TIME,
       to_char(t.START_DATE, 'yyyymmdd hh24:mi:ss')       as START_DATE,
       s.status,
       (select q.SQL_TEXT from v$sql q where q.LAST_ACTIVE_TIME = t.START_DATE
                                         and rownum <= 1) as SQL_TEXT
from v$session s,
     v$transaction t
where s.sADDR = t.SES_ADDR;

4. 若找不到對應的User,則可以通過kill掉死鎖的session程式

SELECT l.SESSION_ID, l.OS_USER_NAME, s.USERNAME, l.OBJECT_ID, l.ORACLE_USERNAME
FROM v$locked_object l,
     v$session s
WHERE l.SESSION_ID = s.SID;

5. 根據SessionID查詢鎖表語句

select sql_text
from v$sql
where hash_value in
      (select sql_hash_value from v$session where sid in (208));

6. 檢視死鎖

select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode, SESS.machine

from v$locked_object lo,
     dba_objects ao,
     v$session sess

where ao.object_id = lo.object_id
  and lo.session_id = sess.sid;
alter system kill session '208,207';

對v$locked_object被鎖物件進行查詢:

      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#;
1741808-10eda729fe7adfd0.png
鎖表sql

分析上圖結果:

第1個Session的id為139對LN_DUE進行了鎖表操作,第2個session的id為141對LN_DUE進行了鎖表操作,於是死鎖產生了。一般為程式碼中使用了兩個Connection,前一個Connection執行完update語句未提交,導致行級鎖未釋放,第2個Connection又去對同一個表進行update,於是只能等待前一個connection釋放行級鎖。

相關文章