我有一些代码如下所示:
using (SqlConnection sqlCon = new SqlConnection("connection string which includes MultipleActiveResultSets=True")
{
using (SqlCommand sqlCmd1 = new SqlCommand("SELECT * FROM MyTable WHERE ProcessedRslt IS NULL", sqlCon)
{
using (SqlDataReader sqlRdr = sqlCmd1.ExecuteReader())
{
using (SqlCommand sqlCmd2 = new SqlCommand("UPDATE MyTable SET ProcessedRslt = @Result WHERE RecordID = @RecordID", sqlCon)
{
sqlCmd2.Parameters.Add("@RecordID", SqlDbType.Int);
sqlCmd2.Parameters.Add("@Result", SqlDbType.Int);
while (sqlRdr.Read())
{
int result = ProcessRecord(sqlRdr["RecordID"], ...) // <- This function takes a bunch of values from the SqlDataReader, performs some fairly complex operations on them and returns a result indicating success or what type failure was encountered.
sqlCmd2.Parameters["@RecordID"].Value = (int)sqlDataReader["RecordID"];
sqlCmd2.Parameters["@Result"].Value = result;
sqlCmd2.ExecuteNonQuery(); // !IS THE LINE I'M CONCERNED ABOUT!
}
}
}
}
}因此,这段代码处于生产环境中,多年来一直运行良好。但偶尔也会出现打嗝,最近这种情况更经常发生。while (sqlRdr.Read())循环顺利地运行了几千次,然后突然间,sqlCmd2.ExecuteNonuery()行导致超时,这是我的异常处理所捕捉到的。
在我的一生中,我无法理解为什么这个简单的UPDATE语句应该在SQL中超时,特别是当同一条语句成功地执行了几千次而没有打嗝的时候。我对Microsoft的维护没有太深的了解,我想知道其他可能正在访问数据库的进程,特别是这个表,是否会导致死锁或其他什么。我无法控制(甚至是完全了解)其他进程在什么时间访问数据库。
但是,我认为UPDATE MyTable SET this WHERE that是一个非常直接的原子查询,不应该同时受到针对DB的其他查询的影响?或者,它位于一个运行时间相当长的using (SqlDataReader...)块中,这是否是问题的一部分?
如果是这样,那么从表中读取大量记录、对每个记录执行任务、然后根据执行任务的结果逐个更新每个记录的惯用方法是什么?这肯定是一个常见的用例吗?
发布于 2020-06-30 12:38:22
我建议您将sqlCmd1 sql命令分页为小部分,以避免可能的超时。服务器可以关闭长时间的活动连接。
https://stackoverflow.com/questions/62657555
复制相似问题