LOCKを使用して、物事をシリアライズ可能にすることができますが、これにより同時実行性が低下します。最初に一般的な条件(「ほとんど挿入またはほとんど選択」)を試し、次に「修復」アクションを安全に処理してみませんか?つまり、「JFDI」パターン...
ほとんどの場合、INSERTが予想されます(ボールパーク70-80%以上):
挿入してみてください。失敗した場合、その行はすでに作成されています。 TRY / CATCHは重複を処理するため、並行性について心配する必要はありません。
BEGIN TRY
INSERT Table VALUES (@Value)
SELECT @id = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE -- only error was a dupe insert so must already have a row to select
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
主にSELECT:
同様ですが、最初にデータを取得してみてください。データなし=INSERTは必要ありません。繰り返しますが、2つの同時呼び出しでINSERTを試行した場合、両方の行でTRY/CATCHハンドルが欠落していることがわかりました。
BEGIN TRY
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
IF @@ROWCOUNT = 0
BEGIN
INSERT Table VALUES (@Value)
SELECT @id = SCOPE_IDENTITY()
END
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
2つ目は繰り返されているように見えますが、非常に同時です。ロックは同じことを達成しますが、同時実行性を犠牲にして...
編集:
なぜしない MERGEを使用するには...
OUTPUT句を使用すると、更新されたものだけが返されます。したがって、OUTPUT句のINSERTEDテーブルを生成するには、ダミーのUPDATEが必要です。多くの呼び出しでダミーの更新を行う必要がある場合(OPによって暗示されるように)、それは大量のログ書き込みです MERGEを使用できるようにします。