3

私は現在、挿入の一部として使用されるファンキーな英数字コードを生成するカスタム定義関数を Oracle 10g で実行する INSERT TRIGGER を持っています。

関数 (またはトリガー) がスレッドセーフであることを確認して、2 人のユーザーが同時にトリガーをアクティブにした場合、トリガー内で使用される関数が両方のユーザーに対して同じコードを返さないようにする必要があります。

トリガーのフローは次のとおりです。

始める

  1. ビジネス ロジックに基づいて続行する必要があるかどうかを判断する
  2. カスタム関数を実行して新しいコードを取得する
  3. 返されたコードを別のテーブルへの挿入として使用する

終わり

主な問題は、ステップ 2 の実行中に別のスレッドがトリガーを起動し、これもステップ 2 に入り、最初のスレッドと同じコードを返す場合です。(これが非常に厳しい状況であることは理解していますが、対処する必要があります)。

これを行う主な方法として、次の 2 つを考えました。

私がこれまでに考えた最善の方法は、トリガーの開始時にトリガーで使用されるテーブルを「排他モード」でロックし、ロックの NOWAIT 属性を指定しないことです。このようにして、その後のトリガーのアクティブ化は、ロックが使用可能になるのを一種の「停止して待機」し、他のスレッドがトリガーで終了するのを待ちます。

テーブルの読み取りを拒否するテーブルをロックしたいのですが、Oracleでこれを行う方法を見つけたようです。

私のアイデアは理想的ではありませんが、うまくいくはずですが、これについてより良いアイデアを持っている人から聞いてみたいです!

与えられた助けに感謝します。

乾杯、マーク

4

3 に答える 3

5

ここで排他性を解決する必要はありません。オラクルは、トランザクションを管理することでそれを行います。

重要なのは、「カスタム定義関数」の呼び出しごとに一意のコードを返す必要があるということです。

これは、システムの日付/時刻を使用しないことを意味しますが、一意性を確保するために別のものを使用します。

私はこれをお勧めします:

select sys_guid() from dual;

あなたの機能をソルトするために使用sys_guid()し、すべてがトリガーランドでうまくいくはずです。

この値で別のテーブルを更新しようとしないでください。そうしないと、テーブルの変更などに対処する必要があります。

編集:明らかに、他のカップルが言及したように、トリガーでシーケンスを使用して関数をシードすることは、Oracleが一意性を強制するための別の良い提案です。ただし、シードとして使用すると予測可能な結果が生成される可能性があるため、「カスタム定義関数」がパスワードのリセットなどである場合は注意してください。

于 2008-12-15T23:51:46.740 に答える
1

「それが何であるかを知る必要はまったくありません。関数が生成するコードにすぎません」適切な答えを出すためには、他のことと私たちが知る必要があるため、時間ベースでなければなりません。あなたのスループットにあるかどうかはわかりません。DBMS_LOCK.REQUEST を 1a、DBMS_LOCK.SLEEP を 2a、DBMS_LOCK.RELEASE を 2b と見なすことができます。これにより、各ロックが 1 秒間保持されるため、1 秒間に 1 つの挿入のみが発生する可能性があります。

シーケンスベースのOracleの場合、同じシーケンスが2回取得されないことが保証されます

セッション/パッケージの状態に依存する場合 (セッション内のインクリメントなど)、セッションでは一度に 1 つの挿入しか実行できません (ただし、複数行の挿入、選択、または複数テーブルの挿入の場合もあります)。 .

データベースの状態に依存する場合 (つまり、関数がクエリを実行する場合)、ステートメントではなくトランザクションで考える必要があります。DBMS_LOCK は引き続き使用できますが、新しいデータがコミットされて表示されるまで待機中のセッションが実際に待機するように、コミット後に手動でロックを解放する必要があります。

于 2008-12-16T02:07:51.863 に答える
1

1 つの解決策は、Oracle シーケンスを使用して、一意の文字列を生成するカスタム コードにフィードすることです。Oracle はこの理由からシーケンスを提供しています。そのため、一意の ID を生成するメソッドはスレッドセーフです。Oracle 9i (私が使用しているバージョン) のドキュメントについては、こちらを参照してください。

于 2008-12-16T04:15:54.693 に答える