如何防止成为僵局受害者?

时间:2016-04-14 18:45:21

标签: c# dataset sqlcommand database-deadlocks sqldataadapter

我得到了这个例外消息:

事务(进程ID 55)在锁资源上与另一个进程发生死锁,并被选为死锁牺牲品。

我的代码中唯一涉及Stack Trace的代码是最后一行:

public static DataTable ExecuteSQLReturnDataTable(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
    using (DataSet ds = new DataSet())
    using (SqlConnection connStr = new SqlConnection(CPSConnStr))
    using (SqlCommand cmd = new SqlCommand(sql, connStr))
    {
        cmd.CommandType = cmdType;
        cmd.CommandTimeout = EXTENDED_TIMEOUT;
        foreach (var item in parameters)
        {
            cmd.Parameters.Add(item);
        }

        try
        {
            cmd.Connection.Open();
            new SqlDataAdapter(cmd).Fill(ds);

这是我用于各种查询的通用方法;我最近没有改变它,也没有见过这个特殊的例外。

我可以做些什么来防止再次抛出此异常?

2 个答案:

答案 0 :(得分:2)

您可以捕获死锁异常并在放弃之前重试X次。

没有神奇的解决方案可以避免死锁。如果SQL Server检测到死锁,它将选择一个要杀死的进程。在某些情况下,您可能遇到了死锁,您的流程很幸运,可以继续。

您可以使用SQL事件探查器捕获死锁。我过去必须这样做,试图弄清楚究竟是什么导致了死锁。这种情况发生的次数越少,追踪的难度就越大。在我们的测试环境中,我们刚刚创建了一些测试代码来从几台不同的机器中锤击数据库,以尝试导致死锁。

在我们的例子中,我们对索引和修改过的数据库触发器进行了一些更改,以尽可能地减少死锁。最后,我们仍然必须将重试作为一个"以防万一"。

答案 1 :(得分:1)

如果您显示传递给ExecuteSQLReturnDataTable的SQL,可能会有所帮助。同时阅读Minimizing Deadlocks

当然,您可能还必须查看导致死锁的其他因素。