天天看點

Oracle 死鎖處理發現死鎖定位 session解決問題總結

鎖機制是Oracle用來滿足隔離性,一緻性的重要機制。但是不合理的業務邏輯可能導緻死鎖的産生,生産環境如果發生大量死鎖,可能對業務造成很大的影響,是以必須及時處理。

發現死鎖

通過 dba_blockers 視圖,可以查到死鎖的程序。

Oracle 死鎖處理發現死鎖定位 session解決問題總結
Oracle 死鎖處理發現死鎖定位 session解決問題總結
我這裡由于是 19c ,是以多了一列 CON_ID ,表示哪個 pdb。

定位 session

-- 通過以下 SQL 定位死鎖發生的 session 及 對象
select lo.session_id,
       s.serial#,
       s.username,
       o.name,
       s.lockwait,
       s.status,
       s.machine,
       s.program
  from v$session s, v$locked_object lo, obj$ o
 where s.sid = lo.session_id
   and lo.object_id = o.obj#;
           
Oracle 死鎖處理發現死鎖定位 session解決問題總結
字段名 含義
SESSION_ID Session ID 。與 SERIAL# 共同确定會話
SERIAL# Session serial number(會話編号)。與 SESSION_ID 共同确定會話
USERNAME Oracle username 。被鎖語句的執行者
NAME 被鎖對象的名字
LOCKWAIT Address of the lock the session is waiting for; NULL if none
STATUS Status of the session
MACHINE Operating system machine name (主機名)
PROGRAM Operating system program name (連接配接用得用戶端類型)
Status of the session:
  • ACTIVE - Session currently executing SQL
  • INACTIVE
  • KILLED - Session marked to be killed
  • CACHED - Session temporarily cached for use by Oracle*XA
  • SNIPED - Session inactive, waiting on the client
-- 通過以下 SQL 可以定位到被阻塞的 SQL 文本
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));
           

解決問題

解決死鎖的方式一般就是殺掉一個 session。

通過上面的查詢定位到了一對 session ,其中 session_id 1457 的 session 阻塞了 session_id 1698 的 session。

那麼最好的處理辦法事殺掉 session_id 1457 的 session (也就是造成阻塞的 session),這樣 被阻塞的 session 上的 SQL 還可以繼續執行。也可以殺掉被阻塞的 session ,這樣被阻塞 session 上的 SQL 就會失敗(不推薦)。

-- 殺掉 session 的 SQL
alter system kill session 'session_id,serial#'; 

-- 該例子中使用的語句如下:
alter system kill session '1457,63336'; 
           

總結

如果生産系統經常出現死鎖,肯定是程式有邏輯上的問題。這個時候就需要通過定位 SQL 找到死鎖的原因,才能從根本上解決問題。