如何防止成为死锁受害者?

Posted

技术标签:

【中文标题】如何防止成为死锁受害者?【英文标题】:How can I prevent becoming a deadlock victim? 【发布时间】:2016-04-14 18:45:21 【问题描述】:

我收到了这个异常消息:

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

堆栈跟踪中涉及的唯一代码行是此处的最后一行:

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);

这是我用于各种查询的通用方法;我最近没有更改它,也从未见过这个特殊的异常。

如何防止再次抛出此异常?

【问题讨论】:

【参考方案1】:

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

没有避免死锁的神奇解决方案。如果 SQL Server 检测到死锁,它会选择要终止的进程之一。在某些情况下,您可能会遇到死锁,而您的进程很幸运能够继续。

您可以使用 SQL Profiler 来捕获死锁。过去我不得不这样做,以试图找出导致死锁的真正原因。这种情况发生得越少,就越难追踪。在我们的测试环境中,我们刚刚创建了一些测试代码来从几台不同的机器上敲击数据库,以尝试导致死锁。

在我们的案例中,我们对索引进行了一些更改并修改了数据库触发器,以尽可能减少死锁。最后,我们仍然不得不将重试作为“以防万一”。

【讨论】:

【参考方案2】:

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

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

【讨论】:

以上是关于如何防止成为死锁受害者?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止CSRF攻击

防止跨站攻击——CSRFToken

如何防止关机钩子陷入死锁?

使用命名管道时如何防止死锁?

如何在单个查询完成执行之前锁定事务以防止出现死锁错误

如何防止非法请求