事务(进程ID 209)在锁定时死锁与另一个进程通信缓冲资源并被选为死锁牺牲品

时间:2015-04-08 18:33:50

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

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

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

System.Web.HttpUnhandledException(0x80004005):抛出了类型为“System.Web.HttpUnhandledException”的异常。 ---> System.Data.EntityCommandExecutionException:从商店提供商的数据读取器读取时发生错误。有关详细信息,请参阅内部异常---> System.Data.SqlClient.SqlException:事务(进程ID 209)在锁定时死锁与另一个进程通信缓冲资源并被选为死锁牺牲品。重新运行该交易。

如何克服这种情况?

我遵循的步骤是,

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

3 个答案:

答案 0 :(得分:2)

您唯一能做的就是检查数据迁移服务。 保持交易尽可能短。不要打开事务,直到你真的要写数据并在写完后立即关闭它。 This可能会有所帮助。

答案 1 :(得分:1)

当两个连接以相反的顺序更新表时,可能会发生

死锁。例如,一个连接插入表" example1"首先然后进入" example2,"而另一个连接插入表" example2"首先然后进入" example1"在交易中。 您可以采取一些措施来避免死锁

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

从MS中查看此link以获取更多详细信息

答案 2 :(得分:1)

考虑到问题的本质,我会考虑使用影子数据库概念。

准备好数据库Y,准备好所有新的数据连接后转到DB Y, 然后在Y生效时更新DB X.当X准备就绪时,将所有新连接重定向回DB X. EF支持动态连接字符串。

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