ここで少し厳しい状況が発生しました。システムで時折デッドロックが発生しています。また、私はデータベースの同時実行に関して強いバックグラウンドをまったく持っていません。
System.Data.SqlClient.SqlException: Transaction (Process ID 69) was deadlocked on
lock resources with another process and has been chosen as the deadlock victim.
Rerun the transaction.
データベースにアクセスするアプリケーションはいくつかあります。Entity Framework を使用してデータベースにアクセスするメインの MVC アプリと、それぞれが ADO.NET と生の SQL を使用して DB にクエリを実行し、BinaryTap ActiveRecord を介してデータを挿入するいくつかの単純なコンソール アプリです。
残念ながら、私はクライアント組織の FNG であるため、新しいアイデアを展開してテストすることはできません。また、SSMS Express を使用しているため、SQL プロファイラーにアクセスできません。しかし、問題をすぐに修正することはそれほど重要ではなく、問題の分析を文書化することがより重要です。
トランザクションを再実行する必要があるというエラー メッセージに真実はありますか? これが DaoBase です。HttpContext ごとに 1 つの ObjectContext を (Db プロパティを介して) 使用しています。私たちは常に Dao の更新 (クエリではない) を SafeAction に入れているので、それらはトランザクションにラップされます。トランザクションを適切に再実行しようとしていますか?
public abstract class DaoBase
{
protected static CaseMateEntities Db
{
get
{
return ContextHelper<CaseMateEntities>.GetCurrentContext();
}
}
protected static void SafeAction(Action<ObjectContext> action)
{
Exception exception = null;
try {
using (var scope = new TransactionScope()) {
try {
if (Db.Connection.State != ConnectionState.Open)
Db.Connection.Open();
if (action != null)
action(Db);
Db.SaveChanges(SaveOptions.DetectChangesBeforeSave);
scope.Complete();
} catch (Exception ex) {
exception = ex;
if (exception is UpdateException)
// TODO: Is this a proper way to rerun a transaction?
scope.Complete();
}
}
if (exception == null) {
Db.AcceptAllChanges();
} else {
throw exception;
}
} finally {
Db.Connection.Close();
}
}
}
他のアプリは、ADO.NET/Raw SQL を介してデータベースにクエリを実行します。それぞれの SELECT ステートメントにはWITH (NOLOCK)
指定がありません。純粋なクエリをロックしたい状況はありますか? また、クエリが作成するロックの種類は、行とページのロックですか? Entity Framework によって生成されたクエリについてはどうですか?クエリをロックしないように EF に指示する必要がありますか?
ここまで読んでくださった皆様、ありがとうございました。私はこれが複雑な問題であることを知っており、やるべきことがたくさんあります..