天天看點

oracle死鎖避免、查詢及處理

什麼是死鎖 

當兩個(或多個)使用者互相等待被對方加鎖的資源時就會發生死鎖(deadlock)。死鎖将導緻相關的事務停止執行。下圖示範了産生死鎖的兩個事務。  

如圖所示,在時間點 A,兩個事務均獲得了更新操作所需資料行上的鎖,此時兩事務均正常,能夠繼續執行。接下來,兩個事務均要更新目前被對方加鎖的資料。是以,在時間點 B 将發生死鎖,因為此時兩個事務都不能獲得繼續執行或終止所需的資源。無論兩個事務等待多久,互相沖突的鎖都無法被釋放,是以此種情況被稱為死鎖。

圖:産生死鎖的兩個事務

oracle死鎖避免、查詢及處理

檢測死鎖 

資料庫能自動地檢測死鎖的情況,復原造成死鎖的某個語句,以便釋放沖突的行級鎖,進而解決死鎖問題。資料庫将向執行了語句級復原的事務傳回一個錯誤資訊。 

避免死鎖 

如果兩個事務需要通路相同的一組表,那麼在兩個事務中按相同的順序對這組表加鎖通常能避免多表死鎖。例如,如果系統中的一個主表及一個明細表都需要更新時,開發者應該遵從一定的規則,如先對主表加鎖,再對明細表加鎖。如果能夠仔細設計類似的規則并嚴格執行,就能從根本上杜絕死鎖的産生。    如果開發者預先知道需要在同一事務内對一系列資源加鎖,那麼應考慮首先對排他性最高的資源加鎖。 

關于資料庫死鎖的檢查方法

一、資料庫死鎖的現象

程式在執行的過程中,點選确定或儲存按鈕,程式沒有響應,也沒有出現報錯。

二、死鎖的原理

當對于資料庫某個表的某一列做更新或删除等操作,執行完畢後該條語句不提

交,另一條對于這一列資料做更新操作的語句在執行的時候就會處于等待狀态,

此時的現象是這條語句一直在執行,但一直沒有執行成功,也沒有報錯。

三、死鎖的定位方法

通過檢查資料庫表,能夠檢查出是哪一條語句被死鎖,産生死鎖的機器是哪一台。

1)用dba使用者執行以下語句

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)用dba使用者執行以下語句,可以檢視到被死鎖的語句。

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))

四、死鎖的解決方法

     一般情況下,隻要将産生死鎖的語句送出就可以了,但是在實際的執行過程中。使用者可

能不知道産生死鎖的語句是哪一句。可以将程式關閉并重新啟動就可以了。

 經常在Oracle的使用過程中碰到這個問題,是以也總結了一點解決方法。

1)查找死鎖的程序:

sqlplus "/as sysdba" (sys/change_on_install)

SELECT s.username,l.OBJECT_ID,l.SESSION_ID,s.SERIAL#,

l.ORACLE_USERNAME,l.OS_USER_NAME,l.PROCESS 

FROM V$LOCKED_OBJECT l,V$SESSION S WHERE l.SESSION_ID=S.SID;

2)kill掉這個死鎖的程序:

  alter system kill session ‘sid,serial#’; (其中sid=l.session_id)

      alter system kill session '710,35184'; (其中sid=l.session_id)

3)如果還不能解決:

select pro.spid from v$session ses,v$process pro where ses.sid=XX and ses.paddr=pro.addr;

  其中sid用死鎖的sid替換: exit

ps -ef|grep spid

  其中spid是這個程序的程序号,kill掉這個Oracle程序

from:http://southking.javaeye.com/blog/550832

select A.SQL_TEXT, B.USERNAME, C.OBJECT_ID, C.SESSION_ID, 

       B.SERIAL#, C.ORACLE_USERNAME,C.OS_USER_NAME,C.Process,

       ''''||C.Session_ID||','||B.SERIAL#||''''

from v$sql A, v$session B, v$locked_object C

where A.HASH_VALUE = B.SQL_HASH_VALUE and

B.SID = C.Session_ID