0

テーブルに挿入される行が 1 つだけであることを確認しようとしていますが、複数のプロセスが互いに衝突し、複数の行が取得されるという問題が発生しています。詳細は次のとおりです(おそらく必要以上に詳細です、申し訳ありません):

「エリア」の階層を保持する Areas というテーブルがあります。各「エリア」には、Orders テーブルに保留中の「注文」がある場合があります。階層化されているため、複数の「領域」を親の「領域」の下にグループ化できます。

FindNextOrder というストアド プロシージャがあります。このストアド プロシージャは、領域を指定すると、次の保留中の注文 (子領域にある可能性があります) を見つけて、それを「アクティブ化」します。「アクティブ化」とは、OrderID を QueueActive テーブルに挿入することを意味します。ビジネス ルールでは、エリアは一度に 1 つのアクティブな注文のみを持つことができます。

したがって、ストアド プロシージャには次のようなステートメントがあります。

IF EXISTS (SELECT 1 FROM QueueActive WHERE <Order exists for the given area>) RETURN
...
INSERT INTO QueueActive <Order data for the given area>

私の問題は、時々、2 つの異なるプロセスがこのストアド プロシージャをほぼ同時に呼び出すことです。それぞれが既存の行をチェックすると、それぞれにゼロが返されます。そのため、両方のプロセスが挿入ステートメントを実行し、1 つではなく 2 つのアクティブな注文が発生します。

これを防ぐにはどうすればよいですか?ああ、たまたま SQL Server 2012 Express を使用していますが、SQL Server 2000、2005、および 2008 でも機能するソリューションが必要です。

私はすでにテーブルを排他的にロックするための検索を行っており、この回答を見つけましたが、これを実装しようとして失敗しました。

4

2 に答える 2

0

selectステートメントでいくつかのクエリヒントを使用します。あなたの手順は共有ロックを取り出しているだけで、他の手順が参加できるため、問題が発生しています。

WITH (ROWLOCK, XLOCK, READPAST) を SELECT にタグ付けします

ROWLOCK は、行のみをロックしていることを保証します。
XLOCK は行の排他ロックを解除し、他の誰もそれを読み取ることができないようにします。
READPAST を使用すると、クエリはロックされた行をスキップして、待機する代わりに作業を続けることができます。

最後のオプションはオプションであり、並行性の要件によって異なります。

詳細情報:
SELECT に対する SQL Server ROWLOCK (存在しない場合) INSERT トランザクション
http://technet.microsoft.com/en-us/library/ms187373.aspx

于 2013-09-20T20:27:56.583 に答える
0

テーブルにアクティブな注文が 1 つある場合に 2 番目のトランザクションをロールバックするトリガーを作成しようとしましたか?

于 2013-09-20T20:58:11.327 に答える