【问题标题】:Transaction (Process ID 209) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim事务(进程 ID 209)在锁上死锁 |与另一个进程通信缓冲区资源,并已被选为死锁牺牲品
【发布时间】:2015-04-08 18:33:50
【问题描述】:

我有一个 ASP.NET Web 应用程序,它从 SQL Server 2008 R2 数据库中获取数据并将其显示给用户。数据库中的表每 30 分钟会填充一次来自另一个服务的最新数据。该服务运行 5 分钟。

我面临的问题是,每当用户在更新表时访问应用程序时,都会引发以下错误,

System.Web.HttpUnhandledException (0x80004005):引发了“System.Web.HttpUnhandledException”类型的异常。 ---> System.Data.EntityCommandExecutionException:从存储提供程序的数据读取器读取时出错。有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException: Transaction (Process ID 209) was deadlocked on lock |与另一个进程通信缓冲区资源,并已被选为死锁牺牲品。重新运行事务。

如何克服这种情况?

我遵循的步骤是,

using (SqlConnection con = new SqlConnection(db.Database.Connection.ConnectionString))
                {
                    con.Open();
                    using (SqlTransaction tran = con.BeginTransaction())
                    {       
                        string queryText = string.Format("DELETE FROM TABLE_NAME", DataDateTime);
                        SqlCommand cmd = new SqlCommand(queryText, con, tran);
                        cmd.ExecuteNonQuery(); 

                        SqlBulkCopy bc = new SqlBulkCopy(con,
                          SqlBulkCopyOptions.KeepNulls, tran);

                        bc.BatchSize = 5000;
                        bc.DestinationTableName = "TABLE_NAME";
                        DataTable data = newIncidentExtractList.ToDataTable();
                        bc.WriteToServer(data);    

                        string updateText = @"Update TABLE_NAME WITH CONDITION";
                        SqlCommand cmdActive = new SqlCommand(updateText, con, tran);
                        cmdActive.ExecuteNonQuery();    

                        string updateTextInactive = @"Update TABLE_NAME WITH CONDITION";
                        SqlCommand cmdInActive = new SqlCommand(updateTextInactive, con, tran);
                        cmdInActive.ExecuteNonQuery();    

                        string updateUnAssigned = @"Update TABLE_NAME WITH CONDITION";
                        SqlCommand cmdUnAssigned = new SqlCommand(updateUnAssigned, con, tran);
                        cmdUnAssigned.ExecuteNonQuery(); 

                        tran.Commit();
                        insertResult = true;
                    }
                    con.Close();
                }

【问题讨论】:

  • 您是删除并重新创建表,删除所有记录并插入新记录还是其他?
  • 我没有删除表格,而是删除所有记录并插入新记录。
  • 当您删除所有条目并重新添加时,该应用程序当前如何工作。您在 1 个事务/提交中执行此操作?
  • 是的,我在 1 笔交易中执行此操作。我只是添加了代码结构。请验证。
  • 并且应用程序可以在更新 TABLE_NAME 的同时,您在逻辑上删除并重新添加一组不同的条目。?哇

标签: c# asp.net sql-server entity-framework entity-framework-6


【解决方案1】:

您唯一能做的就是检查您的数据迁移服务。 尽可能缩短交易时间。在您真正要写入数据并在写入后立即关闭之前不要打开事务。 This 可能会有所帮助。

【讨论】:

    【解决方案2】:
    当两个连接以相反的顺序更新表时,可能会发生

    死锁。例如,一个连接先插入表“example1”,然后插入“example2”,而另一个连接先插入表“example2”,然后再插入事务中的“example1”。 您可以采取一些措施来避免死锁

    • 更改更新表的]冲突连接的顺序。
    • 在您的表 (check this out) 上启用 IRL(插入行锁)
    • 使用较大的填充因子在此表上重新创建聚集索引。 (Check this out)
    • 消除非聚集二级索引(如果可能)

    查看来自 MS 的 link 了解更多详细信息

    【讨论】:

    • 感谢您的建议和链接,我会通过它们。
    • 您尝试过这些步骤吗?
    【解决方案3】:

    鉴于问题的性质,我会考虑使用影子数据库概念。

    您准备 DB Y ,当所有新的数据连接都准备好后,将转到 DB Y, 然后在 Y 处于活动状态时更新 DB X。当 X 准备好时,将所有新连接重定向回 DB X。 EF 支持动态连接字符串。

    如果表不涉及约束和外键,您可以使用影子表并根据当前的 Live 表标志动态访问表 A 或表 B。

    【讨论】:

    • 感谢您的建议。我也会看看这个选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    相关资源
    最近更新 更多