Stack Overflow SQL Server 2005データベースで、いくつかの有害ではあるがまれなデッドロック状態が発生しています。
プロファイラーを添付し、デッドロックのトラブルシューティングに関するこの優れた記事を使用してトレースプロファイルを設定し、多数の例をキャプチャしました。奇妙なことに、デッドロック書き込みは常に同じです:
UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0
他のデッドロックステートメントはさまざまですが、通常は、投稿テーブルを簡単に読み取るだけです。これは常にデッドロックで殺されます。これが例です
SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount],
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId],
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0
完全に明確にするために、書き込み/書き込みのデッドロックは発生していませんが、読み取り/書き込みが発生しています。
現在、LINQクエリとパラメータ化されたSQLクエリが混在しています。with (nolock)
すべてのSQLクエリに追加しました。これはいくつかの助けになったかもしれません。また、昨日修正した1つの(非常に)不適切に記述されたバッジクエリがありました。これは、毎回実行するのに20秒以上かかり、その上で毎分実行されていました。これがいくつかのロックの問題の原因であることを望んでいました!
残念ながら、約2時間前に別のデッドロックエラーが発生しました。同じ正確な症状、同じ正確な犯人の書き込み。
本当に奇妙なことは、上記のロック書き込みSQLステートメントが非常に特定のコードパスの一部であるということです。それはだだけ新しい答えを質問に追加されたときに実行される-それは、新しい回答数と最後の日付/ユーザーと親の質問を更新します。これは、明らかに、私たちが行っている膨大な数の読み取りに比べてそれほど一般的ではありません!私の知る限り、アプリ内のどこにも大量の書き込みは行っていません。
NOLOCKは一種の巨大なハンマーだと思いますが、ここで実行するクエリのほとんどはそれほど正確である必要はありません。ユーザープロファイルが数秒古くなっていてもかまいませんか?
スコットハンゼルマンがここで説明しているように、LinqでNOLOCKを使用するのは少し難しいです。
私たちは使用するという考えでいちゃつく
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
すべてのLINQクエリにこのセットが含まれるように、ベースデータベースコンテキストで。それがなければ、私たちが行うすべてのLINQ呼び出し(まあ、それらの大部分である単純な読み取り呼び出し)を3〜4行のトランザクションコードブロックでラップする必要があります。これは醜いです。
SQL 2005での些細な読み取りが書き込みでデッドロックする可能性があることに、少し不満を感じていると思います。書き込み/書き込みのデッドロックが大きな問題であることがわかりましたが、読み取りますか?ここでは銀行サイトを運営していません。毎回完璧な正確さを要求するわけではありません。
アイデア?考え?
すべての操作に対して新しいLINQto SQL DataContextオブジェクトをインスタンス化していますか、それともすべての呼び出しで同じ静的コンテキストを共有していますか?
ジェレミー、ほとんどの場合、ベースコントローラーで1つの静的データコンテキストを共有しています。
private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
get
{
if (_db == null)
{
_db = new DBContext() { SessionName = GetType().Name };
//_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
return _db;
}
}
すべてのコントローラーに対して、またはページごとに、またはより頻繁に新しいコンテキストを作成することをお勧めしますか?