1

次のOracleログを受け取りました。

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-00120007-0002acbf        82     185     X             67     240           X
TX-0008001c-0009ed94        67     240     X             82     185           X

session 185: DID 0001-0052-00000004 session 240: DID 0001-0043-00000004 
session 240: DID 0001-0043-00000004 session 185: DID 0001-0052-00000004 

Rows waited on:
  Session 185: obj - rowid = 0001285C - AAAShcAAiAAEoVFAAi
  (dictionary objn - 75868, file - 34, block - 1213765, slot - 34)
  Session 240: obj - rowid = 0001285C - AAAShcAAiAAEoRWAA3
  (dictionary objn - 75868, file - 34, block - 1213526, slot - 55)

----- Information for the OTHER waiting sessions -----
Session 240:
  sid: 240 ser: 7 audsid: 32762787 user: 76/NETCRACKER1
    flags: (0x8000041) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
    flags2: (0x40008) -/-
  pid: 67 O/S info: user: oracle, term: UNKNOWN, ospid: 26869908
    image: oracle@opipodb1
  client details:
    O/S info: user: adipoas1, term: unknown, ospid: 1234
    machine: opipoas1 program: JDBC Thin Client
    application name: JDBC Thin Client, hash value=2546894660
  current SQL:
  select o.object_id
  from nc_objects o,
       (select object_id
          from nc_objects
        connect by prior object_id = parent_id
         start with object_id = :a1
        union
        select object_id
          from nc_references
         where reference in (select object_id
                               from nc_objects
                             connect by prior object_id = parent_id
                              start with object_id = :a1)) ids
 where o.object_id = ids.object_id
 order by o.object_id
   for update of o.object_id

----- End of information for the OTHER waiting sessions -----

Information for THIS session:

----- Current SQL Statement for this session (sql_id=3mxkkzhttwa2q) -----
select o.object_id
  from nc_objects o,
       (select object_id
          from nc_objects
        connect by prior object_id = parent_id
         start with object_id = :a1
        union
        select object_id
          from nc_references
         where reference in (select object_id
                               from nc_objects
                             connect by prior object_id = parent_id
                              start with object_id = :a1)) ids
 where o.object_id = ids.object_id
 order by o.object_id
   for update of o.object_id
===================================================

これは、2つの等しいクエリ(ただし、異なるデータを使用している可能性があります)が互いにロックしていることを意味しますか?

もしそうなら、どうやってそれが起こるのでしょうか?-このクエリは順序付けられたシーケンスをロックします。ここでデッドロックを発生させることはできないと思います。

DBはメタモデルobject_id-PK

ありがとう

4

1 に答える 1

4

ORDER BYは、常にデッドロックを防ぐとは限りません

クエリのデッドロックにつながる可能性のあるシナリオは次のとおりです。

  1. セッション1はでクエリを実行します:id=A
  2. セッション2はでクエリを実行します:id=B
  3. セッション1はクエリを実行し:id=B、セッション1はセッション2を待機しています
  4. セッション2は:id=A、デッドロックが発行された状態でクエリを実行します

を発行するSELECT FOR UPDATEと、別のセッションを待つリスクがあります。このセッションがすでに待機している場合は、デッドロックが発生しています。

OLTP環境でデッドロックを回避する一般的な方法の1つは、を発行することだけSELECT FOR UPDATE NOWAITです。待つのではなく、2番目のセッションを失敗させます。


次のコメントを更新

同じテーブルを更新する複数のセッションがあります。あなたは彼らがお互いをブロックする可能性があります。それらを待機させ、複数の行を更新すると、デッドロックが発生する可能性があります。これを管理するための多くのオプションがあります。

  1. セッションをデッドロックさせます。Oracleはこれを自動的に検出し、ロールバックします。Oracleは、トランザクション全体ではなく、セッションの1つの最後のステートメントのみをロールバックします。これは、エラーが発生したセッションを最初にロールバックしてから、後で再試行する必要があることを意味します。

  2. 私がアドバイスしたように、NOWAITでそれらを実行します。
    それらを失敗させたくない場合は、次のことができます。

    1. NOWAITで行をロックする
    2. ORA-56ロールバックの場合
    3. スリープ後(X秒)にトランザクションの最初から再試行します。

    2つのセッションが互いに無期限にブロックできないようにするには、ロールバックする必要があります。

  3. 更新をシリアル化します。これは通常、単一のセッションのみがテーブル(または行の範囲)を同時に更新できることを確認することによって行われます。
    たとえば、すべてのセッションをトランザクションテーブルに挿入し、1つのジョブで変更を最終テーブルにマージすることができます。同時セッションはお互いをブロックできませんでした。これは明らかにメインテーブルへの更新を延期します(少なくともコミット後)。

デッドロックの検出を制御できないため、オプション1はお勧めしません(したがって、最適化することはできません)。

于 2013-02-07T16:12:27.690 に答える