处理 Sql Server 死锁的最佳方法?
Best way to deal with deadlock in SqlServer?
我在 SqlServer 2008 上经常遇到死锁。目前,我的数据访问层中有以下代码来处理它。它基本上捕获了死锁并尝试使用新连接重新提交命令。没有交易。但它似乎不起作用——用户仍然会遇到异常,而我的日志显示大多数异常都是死锁。谁能告诉我我做错了什么?谢谢
private static SqlDataReader ExecDataReader(SqlCommand comm, CommandBehavior behavior)
{
try { return comm.ExecuteReader(behavior); }
catch(SqlException ex)
{
if(ex.Number == 1205 && comm != null)
{
// Deadlock. Can't resubmit with the same connection,
// have to recreate it.
SqlParameterCollection pars = comm.Parameters;
string str = comm.Connection.ConnectionString;
string sproc = comm.CommandText;
int t = comm.CommandTimeout;
try
{
comm.Cancel();
if(comm.Connection != null &&
comm.Connection.State != ConnectionState.Closed)
comm.Connection.Close();
}
catch { }
// Trying to execute it after a random number of seconds
// in order not to get a deadlock again by executing both
// deadlocked commands at the same time. The GetRamdom
// method works as expected, returns totally random number
// in expected range
Thread.Sleep(GetRandom());
SqlConnection conn2 = new SqlConnection(str);
conn2.Open();
SqlCommand comm2 = conn2.CreateCommand();
comm2.CommandText = sproc;
comm2.CommandType = CommandType.StoredProcedure;
comm2.CommandTimeout = t;
CopyParameters(pars, comm2);
return ExecDataReader(comm2, behavior);
}
else throw;
}
}
你的 C# 看起来不错。但有时由于各种原因,死锁是不可避免的。您需要检测仍然发生死锁的 statement/sproc 并使用 sp_getapplock 在服务器级别锁定该代码。
读取导致死锁并不常见,但它可能会发生
仅当它与更新事务冲突时才会发生
查看所有读取和更新
我知道我会为此受到抨击,但请尝试使用 reader 命令(无锁定)
你可能会得到脏读,但你的读不会导致死锁,也不会成为死锁的受害者
如果可行,您可以尝试 rowlock
也许 post 锁定和更新命令
你想要的是一致的更新顺序
尝试分解更新
如果你有时真的需要更新很多行,你最好使用 tablock
另一件要看的事情是你进进出出的读者
不要在 Reader.Read 中进行处理并保持连接打开
完成后立即关闭 reader 和连接
我在 SqlServer 2008 上经常遇到死锁。目前,我的数据访问层中有以下代码来处理它。它基本上捕获了死锁并尝试使用新连接重新提交命令。没有交易。但它似乎不起作用——用户仍然会遇到异常,而我的日志显示大多数异常都是死锁。谁能告诉我我做错了什么?谢谢
private static SqlDataReader ExecDataReader(SqlCommand comm, CommandBehavior behavior)
{
try { return comm.ExecuteReader(behavior); }
catch(SqlException ex)
{
if(ex.Number == 1205 && comm != null)
{
// Deadlock. Can't resubmit with the same connection,
// have to recreate it.
SqlParameterCollection pars = comm.Parameters;
string str = comm.Connection.ConnectionString;
string sproc = comm.CommandText;
int t = comm.CommandTimeout;
try
{
comm.Cancel();
if(comm.Connection != null &&
comm.Connection.State != ConnectionState.Closed)
comm.Connection.Close();
}
catch { }
// Trying to execute it after a random number of seconds
// in order not to get a deadlock again by executing both
// deadlocked commands at the same time. The GetRamdom
// method works as expected, returns totally random number
// in expected range
Thread.Sleep(GetRandom());
SqlConnection conn2 = new SqlConnection(str);
conn2.Open();
SqlCommand comm2 = conn2.CreateCommand();
comm2.CommandText = sproc;
comm2.CommandType = CommandType.StoredProcedure;
comm2.CommandTimeout = t;
CopyParameters(pars, comm2);
return ExecDataReader(comm2, behavior);
}
else throw;
}
}
你的 C# 看起来不错。但有时由于各种原因,死锁是不可避免的。您需要检测仍然发生死锁的 statement/sproc 并使用 sp_getapplock 在服务器级别锁定该代码。
读取导致死锁并不常见,但它可能会发生
仅当它与更新事务冲突时才会发生
查看所有读取和更新
我知道我会为此受到抨击,但请尝试使用 reader 命令(无锁定)
你可能会得到脏读,但你的读不会导致死锁,也不会成为死锁的受害者
如果可行,您可以尝试 rowlock
也许 post 锁定和更新命令
你想要的是一致的更新顺序
尝试分解更新
如果你有时真的需要更新很多行,你最好使用 tablock
另一件要看的事情是你进进出出的读者
不要在 Reader.Read 中进行处理并保持连接打开
完成后立即关闭 reader 和连接