.NET Webアプリケーションでは、2つの部分に分かれているルーチンがあります。 1をすることができ、時には他のものを呼び出さずに呼び出されるため、時間のほとんどは日常の両方の部分が次々と呼ばれ、Sql Server 2012ロック(UPDLOCK)の奇妙な問題
var result = Method1(someParams);
var finalResult = Method2(result);
は、それらが二つに分割されています。どちらのメソッドも内部的にテーブルTable1
のデータを照会します。上記の2つのメソッドのパラメータが異なるので、それらが実行する選択クエリも異なりますが、これらの2つのメソッドのいずれかによって選択される行をロックしたいので、もう一方のメソッドはその前に選択できませんそれを最初に照会したものが完成しました。選択したデータは後で更新する必要があるため、selectクエリではUPDLOCK
というキーワードを使用しますが、上記のように2つのメソッドのパラメータが異なるため、最良の結果を得るために行ったのは次のとおりです。
Method1
クエリ
次に、Id
を選択して次のクエリを実行して、すべての列を取得します。 (idが外部からそれに渡されるように)
SELECT Id, Column1, Column2, Column3, Column4
FROM Table1 WITH (UPDLOCK, INDEX (PK_Table1))
WHERE Id = @IdParam
Method2
は、2番目のクエリを実行します。したがって、同じレコードに対してMethod1
とMethod2
が同時に呼び出されると、同じ行に対してUPDLOCK
を取得する必要があるデータを更新する前に、別のレコードを待つことになります。
私はデータベースが何らかの理由でインデックスを切り替えていると考えていたので、クエリにはINDEX(PK_Table1) --(Primary Key)
も含まれていました。
私が時折実行する問題は、これらのメソッドが同時に(同じ行に対して)4回以上呼び出されたときに、ロック機構が正しく機能しないことです。レコードが選択されたときにロックされていないことを直接意味する結果が表示されます。このような場合には、上記のクエリを含むプロシージャを変更するだけです(クエリを変更せずに、おそらく再コンパイルする必要があります)。上記のメカニズムが正しく動作するかどうかをチェックするテストが書かれているので、変更が役立つことがわかります。問題があることを検出した後、プロシージャを変更する前に、誤った結果をもたらすテストを実行し、ロックが正しく機能していない場合は発生しないはずです。これら2つのプロシージャを変更した後、テストを再実行しても問題ありません。
このケースは1〜2ヶ月に1回出現しますが、検出されて修正される前に実際にはダメージを受けます。それはすでに4回起こっています。 3回目に発生したときは、WITH
句にINDEX(PK_Table1)
を追加しました。これは修正であると確信していましたが、もう一度起こりました。
私はこれを再現できるかどうか試してみることに興味があります。しかし、SQL Serverがバグを起こす可能性は低いですが、SPはトランザクションなしでどこかで呼び出されている可能性が低いと思わなければなりません。 あなたの最後の返信から、あなたの.netコードでトランザクションをコミットしているという私の悪い回答に変えますか?その場合は、トランザクション管理をSPコードに移行することを検討しましたか? –
SQL 2012のビルド、データベースが設定されている互換性レベル、データベースでreadcommittedsnapshotおよび/またはスナップショットの分離が有効になっているかどうか、およびトランザクションで使用する分離レベルを尋ねることはできますか? –
はいアプリケーションは.NET環境で実行されています。正確には、ASP.NET MVC 4です。これらのSQLプロシージャはMethod1とMethod2から実行され、他の誰もその存在を気にすることはありません。問題はトランザクションのオープン/コミットであることが非常に疑わしいです。 (.NET側) – Dimitri