【发布时间】:2015-10-13 19:57:11
【问题描述】:
我有一些代码定期对 SQL Server 数据库运行查询并将行存储在字典中。这段代码在我们的生产环境中运行了大约 3 年。就在最近,它因未处理的异常而崩溃。出于故障排除的目的,我删除了除列读取之外的所有内容,并将所有内容包装在一个 try-catch 中。这是一个例外:
System.Data.dll 中发生了“System.Data.SqlClient.SqlException”类型的第一次机会异常 超时已过。在操作完成之前超时时间已过或服务器没有响应。
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj,UInt32 错误) 在 System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult,TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 在 System.Data.SqlClient.TdsParserStateObject.ReadByteArray(字节 [] 缓冲区,Int32 偏移量,Int32 长度) 在 System.Data.SqlClient.TdsParser.SkipValue(SqlMetaDataPriv md,TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParser.SkipRow(_SqlMetaDataSet 列,Int32 startCol,TdsParserStateObject stateObj) 在 System.Data.SqlClient.SqlDataReader.CleanPartialRead() 在 System.Data.SqlClient.SqlDataReader.ReadInternal(布尔 setTimeout)
我正在使用与以下内容非常相似的东西:
// query is a simple select from 1 table, not long running by any means
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock)"; //connection timeout
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock) order by col1, col2"; //connection does not time out
SqlCommand command = new SqlCommand(query,connection)
SqlDataReader reader = command.ExecuteReader();
while (!reader.IsClosed && reader.Read()) {
try {
string test0 = reader[0].ToString();
string test1 = reader[1].ToString();
string test2 = reader[2].ToString();
string test3 = reader[3].ToString();
// here is where I would normally processes and store into dictionary
}
catch (Exception e){
//make some noises
}
}
当我使用其他方法运行查询时,它几乎立即返回(不到一秒),但为了看看会发生什么,我将 CommandTimeout 增加到 60 秒(从默认的 30 秒),这只是增加了我的程序在抛出异常之前挂起的时间。
在@frisbee 的建议下,我在查询中添加了一个 order by 子句,这会阻止连接超时。
我认为正在发生的事情是Read() 操作之一没有返回,然后导致连接超时,但我不知道是什么原因造成的。这通常发生在读取第 3 列时的某一行,但并非总是如此。查询返回不到 50k 行,有时它会通过所有行,有时只通过 15k
【问题讨论】:
-
如果您怀疑列访问是罪魁祸首,请将其删除(出于消除目的...)。将
reader.FieldCount聚合到您的循环中的int中,并且什么也不做(这只是为了让您以某种方式“触摸”每一行)。看看你是否还有超时。 -
相同的结果,除了它在 Read() 上抛出异常
-
所以现在你知道它不是列(不太可能开始)。如果这确实不是数据库问题,我会感到非常惊讶。自 3 年前以来发生了什么变化?更多数据?
-
这不是生产修复,而是尝试使用 (nolock)。如果问题消失,那么问题很可能是锁。在表上运行 dbcc checkdb 并进行 defrag - 您可能在 SQL 端遇到数据问题。
-
然后看看你是如何处理连接的。您是否正确处理 rdr?
标签: c# .net sql-server