我怎样才能避免成为僵局的受害者?

How can I prevent becoming a deadlock victim?

我收到此异常消息:

事务(进程 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);

这是我用于各种查询的通用方法;我最近没改过,以前也没见过这种特殊的异常。

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

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

没有避免死锁的灵丹妙药。如果 SQL 服务器检测到死锁,它将选择要终止的进程之一。在某些情况下,您可能遇到了死锁,而您的进程幸运地继续了。

您可以使用 SQL Profiler 来捕获死锁。过去我不得不这样做,试图弄清楚到底是什么导致了死锁。这种情况发生的次数越少,追踪起来就越困难。在我们的测试环境中,我们刚刚创建了一些测试代码来从几台不同的机器上敲击数据库以尝试导致死锁。

在我们的案例中,我们对索引进行了一些更改并修改了数据库触发器,以尽可能减少死锁。最后我们仍然不得不将重试实现为 "just in case".

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

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