ORA-2049錯誤解決過程

yangtingkun發表於2008-04-30

今天協助其他部門解決了這個錯誤。

 

 

由於是在其他人的機器上解決的問題,且由於時間比較緊迫,問題需要馬上解決,因此沒有留下相應的解決步驟,只好根據回憶來描述一下問題,以及解決思路和步驟。

首先看到的現象是透過DBLINK向遠端資料庫的插入記錄時出現了上面的錯誤,除了這個錯誤資訊外,後面跟著ORA-2063錯誤。

ORA-02049: timeout: distributed transaction waiting for lock
Cause: exceeded INIT.ORA distributed_lock_timeout seconds waiting for lock.
Action: treat as a deadlock

看到這個錯誤,第一個反應是碰到了分散式事務的兩階段提交,本地或遠端資料庫的事務處於IN DOUBLE狀態,需要人工進行干預。

於是詢問是否資料庫異常關閉過。得到的答覆是本地資料庫確實在昨天晚上異常關閉,且關閉的時候可能正在執行類似的操作。

看來問題和我預料的基本一致,就是分散式事務在提交和回滾階段,其中一個資料庫發生了異常,導致兩個資料庫的事務狀態不一致所引發的問題。這個時候的做法是人工干預,強制回滾IN DOUBLE狀態的事務。

於是查詢遠端資料庫的DBA_2PC_PENDING檢視,奇怪的是未發現任何記錄。於是查詢本地資料庫的DBA_2PC_PENDING,也未發現任何的記錄。分別查詢遠端資料庫和本地資料庫的DBA_2PC_NEIGHBORS檢視,仍然沒有發現任何的記錄。莫非在我檢查的這個時間內,Oracle已經自動解決了問題,再次執行遠端插入語言,錯誤依舊。看來可以確定的是,問題並不是分散式事務引起的。

仔細觀察錯誤資訊,發現錯誤資訊中雖然包含了分散式事務,但是根據錯誤資訊的描述,錯誤並不是分散式事務引起的,而是分散式事務無法獲取鎖資源。看來開始是沒有仔細觀察錯誤資訊,而僅僅根據分散式事務就盲目作出了錯誤的判斷。

現在的問題其實和普通資料庫中的鎖問題沒有多大的區別,只不過如果目標表被鎖,那麼本地發起的DML會一直處於等待狀態,而不會報錯。而遠端發起的DML則會在等待時間超過資料庫初始化引數distributed_lock_timeout的設定後報錯ORA-2049

確定了問題就好辦了,告訴他們只需要找到持有鎖的會話,就可以看到是誰鎖住了表,如果是被某個人的操作鎖住,通知這個人提交就可以了。如果無法使其提交,或者被程式鎖住,可以透過ALTER SYSTEM KILL SESSION命令將會話殺掉,這樣目標表上的鎖就被清除掉了。

不過他們說,他們已經進行了類似的操作,不過那個持有鎖的會話沒有辦法殺掉。沒有辦法殺掉到並不奇怪,很多時候OracleALTER SYSTEM KILL SESSION命令都無法及時的將會話清除掉,一般情況下,當會話處於繁忙的工作狀態,Oracle需要等當前的會話操作告一段落,才能清除會話,而這需要比較長的等待時間。這時一般在作業系統上直接kill對應的程式ID

查詢遠端資料庫的V$LOCK檢視,果然發現有一張表被鎖,用V$LOCKID1列關聯DBA_OBJECTSOBJECT_ID列,發現被鎖住的就是目標表。查詢V$SESSION,發現持有鎖的會話狀態已經是KILLED狀態。

現在只有兩個方法,一個是等Oracle自己去清理這個會話,當然這可能會等待相當長的一段時間,另一個是利用作業系統命令直接KILL會話對應的程式。由於急需解決這個問題,而採用了後面的方法。不過因為當前作業系統為windows環境,因此沒有辦法直接殺掉對應的執行緒。只能採用Oracle提供的orakill命令。

由於很少管理Windows環境下的Oracle,因此orakill命令還是第一次使用,透過幫助看到orakill後面的兩個引數分別是sidthread,就想當然的將會話的SID和程式的SPID作為引數,結果得到了類似下面的錯誤:

E:\>orakill 135 2415

Could not attach to Oracle instance 135: err = 2

這時才發現orakill裡面的SID引數居然指的是Oracleinstance名稱,改成例項名稱和對應的SPID後,順利的將會話資訊清除。

再次嘗試遠端插入,插入順利完成。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-257186/,如需轉載,請註明出處,否則將追究法律責任。

相關文章