这里有点棘手:我们的系统偶尔会遇到死锁。而且我根本没有强大的数据库并发背景。
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.
有几个应用程序访问数据库:使用实体框架访问数据库的主 MVC 应用程序和几个简单的控制台应用程序,每个应用程序都使用 ADO.NET 和原始 SQL 查询数据库,并通过 BinaryTap ActiveRecord 插入数据。
不幸的是,我是客户组织的 FNG,所以我无法部署和测试新想法。此外,我们使用的是 SSMS Express,所以我无法访问 SQL Profiler。但我立即解决问题并不重要,更重要的是我记录我对问题的分析。
当错误消息说我应该重新运行事务时,它是否有任何真实性?这是我们的 DaoBase - 每个 HttpContext 使用一个 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)
指定 - 也许他们应该?在任何情况下您确实希望锁定纯查询?查询会创建哪些类型的锁:行锁和页锁?实体框架生成的查询呢,我应该告诉 EF 不要锁定查询吗?
感谢所有阅读本文的人。我知道这是一个复杂的问题,我有很多阅读要做..