在SqlServer中处理死锁的最佳方法是什么?

时间:2015-06-24 15:25:06

标签: sql-server tsql sql-server-2008-r2 deadlock database-deadlocks

我在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;
        }
    }

2 个答案:

答案 0 :(得分:1)

你的C#看起来很好。但是,由于各种原因,有时死锁是不可避免的。您需要检测仍然发生死锁的语句/ sproc,并使用sp_getapplock在服务器级别锁定该代码。

答案 1 :(得分:1)

读取导致死锁并不常见,但可能会发生这种情况 只有在与更新事务冲突时才会发生这种情况

查看所有阅读和更新

我知道我会因此受到抨击,但尝试使用(无锁定)读取器命令 你可以得到脏读,但是你的读取不会导致也不会成为僵局的受害者 如果可以,你可以试试rowlock

也许发布锁定和更新命令

您想要的是一致的更新顺序
尝试并分解更新
如果你真的需要多次更新很多行,那么你最好选择一个制表符

要看的另一件事是你已经进入的读者并离开了 不要在Reader.Read中进行处理并保持连接打开 完成后立即关闭阅读器和连接