ORA-00060とは

ORA-00060はデッドロックを検出した場合に発生するエラーです。デッドロックとはロックが循環した状態(AはBを待ちBはAを待っているような状態)であり、 この状態になると処理が永遠に終わらないためORACLEはデッドロックの発生を検知するとデッドロックの原因となっている処理の一つをORA-00060のエラーで異常終了させ、エラーにした処理を実行する前の状態までロールバックします。 なお、トランザクション自体がロールバックされるわけではないので注意が必要です。


対策

ORA-00060の原因となったSQLがユーザアプリケーションが実行したSQLの場合はユーザアプリケーションの問題であるため基本的にはユーザアプリケーション側で対応が必要です。 対策としては必ず一定の順番でロックするようにする、同時実行タイミングをずらす、ロックする可能性のある行やオブジェクトをfor update等でロックできることを確認した上で処理するようにするといった方法が考えられます。 再帰SQLや単一セッション内でORA-00060が発生している場合は不具合の疑いがあるためサポートに相談をしたほうがよいでしょう。

確認

ORA-00060が発生した場合アラートログに以下のような記録がされるとともに、シングル環境においてはORA-00060が発生したプロセスのトレースファイルにデッドロックの解析情報が出力されます。 このトレースから原因となったSQLやロックの種類、セッション情報等を確認することができます。
Sat Apr 30 22:36:03 2011
ORA-00060: Deadlock detected. More info in file j:\program\oracle\diag\rdbms\orcl112\orcl112\trace\orcl112_ora_3916.trc.
RAC環境の場合は以下のような出力となりORA-00060というエラーコードは出力されず、トレースの内容も全く異なるため注意が必要です。 出力される内容もシングル環境のような明快な待機グラフが出てこないケースが多いためイベント設定により合わせてシステムステートダンプを出力させるようにしたほうがよいです。
Sat Apr 30 23:49:55 2011
Global Enqueue Services Deadlock detected. More info in file
 /app/diag/rdbms/rac112/rac1121/trace/rac1121_lmd0_4240.trc.

デッドロックトレースの見方

シングル環境のトレースだと以下のような内容がわかります。(以下は↓のトレースからの分析)

・SID=5と11の2セッション間でデッドロックが発生(Deadlock graphより)し、SID=11がora-00060のエラーを受けた(トレースの発生セッションがSID=11のため)

・それぞれTXエンキューのXモードの獲得でロックしている。つまり、一般的な行ロックによるデッドロック((Deadlock graphより))

・デッドロック時に待機していたオブジェクト情報は以下のSQLで求めることができる
select owner || '.' || object_name from dba_objects where object_id in (80075,80076)
⇒TEST.TBL1表とTEST.TBL2表だった。
 ⇒さらにrowidも出力されているため以下のSQLでロック待機していた行も特定可能
  select * from tbl1 where rowid = 'AAATjLAAEAAF2pLAAA'
  select * from tbl2 where rowid = 'AAATjMAAEAAF2pTAAA'

・SID=11のセッションはsqlplus(*** MODULE NAME:(SQL*Plus)より)で接続しており実行していたSQLは「update tbl1 set col1 = col1 +1 where col1 = 1」である(Current SQL Statement for this session (sql_id=cmwaw7ngdmwu9)より)。

・Information for the OTHER waiting sessionsセクションより、SID=5のセッションはwin2というマシンからsqlplusで接続しており、接続は共有サーバ接続、実行していたSQLは「update tbl2 set col1 = col1 +1 where col1 = 1」である。

その他、Resource Nameにある「TX-000a0006-00001bdd」という記述はV$LOCKのTYPE='TX',ID1=655366(16進数の「000a0006」を10進変換する),ID2=7133(同じく10進変換する)に対応するのでV$LOCKを定期取得していればその情報とも突合せ可能。

*** 2014-09-02 16:08:18.492
*** SESSION ID:(11.17) 2014-09-02 16:08:18.492
*** CLIENT ID:() 2014-09-02 16:08:18.492
*** SERVICE NAME:(SYS$USERS) 2014-09-02 16:08:18.492
*** MODULE NAME:(SQL*Plus) 2014-09-02 16:08:18.492
*** ACTION NAME:() 2014-09-02 16:08:18.492
・・・
*** 2014-09-02 16:08:18.492
DEADLOCK DETECTED ( ORA-00060 )
 
[Transaction Deadlock]
 
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:
 
Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-000a0006-00001bdd        28      11     X             40       5           X
TX-00060017-00001a74        40       5     X             28      11           X
 
session 11: DID 0001-001C-00000008	session 5: DID 0001-0028-00000001 
session 5: DID 0001-0028-00000001	session 11: DID 0001-001C-00000008 
 
Rows waited on:
  Session 11: obj - rowid = 000138CB - AAATjLAAEAAF2pLAAA
  (dictionary objn - 80075, file - 4, block - 1534539, slot - 0)
  Session 5: obj - rowid = 000138CC - AAATjMAAEAAF2pTAAA
  (dictionary objn - 80076, file - 4, block - 1534547, slot - 0)
 
----- Information for the OTHER waiting sessions -----
Session 5:
  sid: 5 ser: 7 audsid: 45952341 user: 86/TEST flags: 0x8000045
  pid: 40 O/S info: user: SYSTEM, term: WIN2, ospid: 6104
    image: ORACLE.EXE (SHAD)
  client details:
    O/S info: user: win2\user1, term: WIN2, ospid: 2680:7772
    machine: WORKGROUP\WIN2 program: sqlplus.exe
    application name: SQL*Plus, hash value=3669949024
  current SQL:
  update tbl2 set col1 = col1 +1 where col1 = 1
 
----- End of information for the OTHER waiting sessions -----
 
Information for THIS session:
 
----- Current SQL Statement for this session (sql_id=cmwaw7ngdmwu9) -----
update tbl1 set col1 = col1 +1 where col1 = 1
★ORACLE案件承ります