1
                if exists (select 1 from schema.TableName (nolock) where Id = @id) 
                update schema.TableName set DocumentXML = @documentXml, ClientDocumentGUID=@clientDocGuid, Incomplete = @incomplete where Id = @id
                else
                insert into schema.TableName
                select @id, @templateId, @clientVisitGuid, @clientGuid, @chartGuid, @scmDocumentGuid, @clientDocGuid, @incomplete, getdate(), @createdByGuid, @documentXml

上記のクエリを実行するC#プログラムがあります。行が2回挿入される状況が発生します。問題はこのクエリだと思います。アイデアは、同じを指定してクエリを2回実行できるということ@Idです。1回目は挿入、2回目は更新である必要があります。

クエリに。があることに注意してください(no lock)。これは、クエリが必ずしもFIFO方式で実行されるとは限らないことを意味しますか?2行の問題は、このクエリを非同期で実行した場合にのみ発生する可能性があると思います。

4

3 に答える 3

1

2つのリクエストを同時に処理する場合、最初のテーブルのすべてのロックを無視するため、両方が挿入されます。このような場合にマージを使用するのが好きです。または、ロックなしを削除して、トランザクション分離レベルがスナップショットまたはシリアル化されていることを確認します。

于 2012-10-10T20:53:26.973 に答える
0

トランザクション分離レベルに応じて、クエリを並行して実行できます...

于 2012-10-10T20:38:48.097 に答える
0

NOLOCKヒントを使用すると、SQLServerはすべてのロックを無視します。つまり、クエリが変更されている途中で値を読み取ることになり、完全なガベージが返される可能性があります。

ただし、NOLOCKヒントを削除するだけでは不十分です。すべてのステートメントが、呼び出し元のアプリケーションまたはプロシージャ内のトランザクション内で実行されることを確認する必要があります。手順を使用する場合は、最初にこれを確認してください:手順をロールバックする方法

ステートメントをトランザクションでラップした後、IF EXISTSステートメントが行を更新または排他的にロックして、他の誰かがステートメントの間に行を挿入できないようにする必要があるため、UPDLOCKまたはXLOCKが必要です。ヒント。行はまだ存在しない可能性があるため、これはシリアル化可能なトランザクション分離レベルでのみ可能です。

これらすべてを実装した後でも、この設定で読み取りを無駄にしています。これは、後でパフォーマンスの問題になる可能性があります。

-

簡単に言うと、JoshBerkeが示唆したように、この場合は実際にMERGEステートメントを使用する必要があります。これにより、問題を防ぎながら、より速く、より簡単に保守できます。ただし、2008年以降が必要です。詳細については、 http://msdn.microsoft.com/en-us/library/bb510625.aspxを参照してください。

于 2012-10-11T02:41:14.870 に答える