2

複数のマシンで実行され、Oracle データベースにアクセスするコードがいくつかあります。行をロックすることにより、このデータベースを (特に) 異なるマシン間の同期オブジェクトとして使用します。

私が抱えている問題は、プロセスが開始されたときに、データベースに同期に依存するものがまだなく、unique constraint violatedすべてのプロセスが同時に挿入しようとするため、プロセスが Oracle 例外を取得することです。

今のところ私の解決策は、その正確な例外をキャッチして無視することですが、アプリケーションの通常のワークフローで例外がスローされるのはあまり好きではありません。

データベースでアトミックに「テストして挿入」するより良い方法はありますか? 行を挿入するときにテーブル/パーティション全体をロックすることは、受け入れられる解決策ではありません。

それが私の解決策だと思ってチェックmerge intoしましたが、同じ問題が発生します。

4

2 に答える 2

4

DBMS_LOCK を使用すると、Oracle データベースが行やその他のリソースをロックする場合と同じロック モデルをユーザー アプリケーション コードで実装できるようになります。タイプ 'UL' (ユーザー ロック) のエンキューを作成し、リソース名を定義してから、複数のセッションを心ゆくまでロックすることができます。どこかのテーブルのデータに依存する必要はありません。排他ロックと共有ロックの両方をサポートしているため、同時に実行できるプロセス (共有ロックを取得する場合) または排他的に実行する他のプロセス (排他ロックを取得する場合) があり、共有ロックの背後で自動的にキューに入れられます。他のタイプのプロセスなどによって保持されている (ある場合)。

これは非常に柔軟なロック モデルであり、実装するためにテーブルのデータに依存する必要はありません。

DBMS_LOCK パッケージの詳細については、Oracle PL/SQL Packages and Types Reference を参照してください。

それが役立つことを願っています。

于 2012-09-05T12:58:16.413 に答える
2

PK が一意ではないインデックスによってポリシングされている場合、すぐにエラーが発生することはありません。次のことを考慮してください。

<<SESSION 1>>
SQL> create table afac (
  2     id number,
  3     constraint afac_pk primary key (id) 
  4        deferrable /* will cause the PK to be policed by a non-unique index */
  5  );

Table created.

SQL> insert into afac values (1);

1 row created.

<<SESSION 2>>    
SQL> insert into afac values (1); /* Will cause session 2 to be blocked */

セッション 2 は、セッション 1 がコミットまたはロールバックされるまでブロックされます。ただし、このメカニズムが要件と互換性があるかどうかはわかりません。

于 2012-09-05T13:30:55.067 に答える