ネットワークを介してデータベースに挿入を実行していますが、既に挿入したデータを挿入しないようにしたいと考えています。クライアントは Web ブラウザーで実行され、Javascript を使用して、挿入するデータを含む XMLHttpRequest をサーバーに送信します。エラーが発生した場合は、後で再試行する必要があります。たとえば、一時的なネットワーク エラーが発生している可能性があります。ただし、リクエストがサーバーを通過した後、成功の応答が返される前にネットワークがダウンする可能性があるため、挿入が成功したことが通知されるという保証を得ることができることを知る方法はありません。これは私には非常にありそうにないように思えますが、特定のエントリがそこにあってはならないことを知る方法がないため、データベースが完全に台無しになります。
2 に答える
挿入するデータの有無を使用して、2 番目の同一のトランザクションが発生した場合に単純に無視されるようにします。何かのようなもの:
INSERT MyTable (Value1, Value2, Value3)
SELECT @Value1, @Value2, @Value3
WHERE
NOT EXISTS (
SELECT *
FROM dbo.MyTable T
WHERE
T.Value1 = @Value1
AND T.Value2 = @Value2
)
;
これは、2 つのクライアントが同時に同じアクションを実行しようとする潜在的な競合状態を完全に解決するわけではないことに注意してください。EXISTS
句はINSERT
操作の前に時間内に実行され、これにより 2 つのクライアントが挿入を試みる可能性があります。したがって、次のようなロックを追加する必要がありますWITH (UPDLOCK, HOLDLOCK)
(行が存在しない場合、無関係なデータの挿入をブロックできる範囲ロックを取得する必要があるため、同時実行には恐ろしいことです)、またはクライアントで重複キーに関するエラーを適切に許容する必要があります。
クライアントがデータを送信する限り、データの複製が実際に問題ない場合は、いくつかの方法で対応できます。
一意になるまでテーブルに列を追加します。
または、トランザクションの一部であるタイムスタンプ/シリアル番号を作成し、(データベース トランザクション内で) 挿入した後、このシリアル番号をテーブルに記録します。このシリアル番号がないこととインサートを関連付けます。
クライアントが送信されたリクエストを確認できるまで保持するための戦略を開発することは、最初に重複した試行の一部を同時に防止する追加の保護レイヤーになる可能性があります-今確認応答を取得できなくても、後で受信する場合、キューに入れられた送信済みトランザクションを確認/削除します。
これを一般化して と の重複を防ぐDELETE
には、 rowversion 型の列をUPDATE
追加する必要があります。この値をすべてのクエリの句に含めると、最後に読んだ後に他の誰かが行に触れた場合、それらのクエリは行に影響しません。行が影響を受けていないことを検出し、後で何らかのインテリジェントな処理を行う必要がありますが、これは非常に困難な場合がありますが、少なくとも編集の競合または重複したアクションを検出して回避しました。WHERE
問題が特定の行に対する特定の編集に切り分けられない場合は、新しい質問をして、具体的な例をいくつか提供して、より良い提案を得ることができます。新しい質問へのリンクを記載したコメントを私に投げてください。見てみます。