我有一些代码会定期对SQL Server数据库运行查询并将行存储在字典中。此代码在我们的生产环境中运行良好约3年。就在最近,它已经因未处理的异常而崩溃。出于疑难解答的目的,除了列读取之外,我删除了所有内容,并将所有内容包装在try-catch中。这是一个例外:
System.Data.dll中发生了'System.Data.SqlClient.SqlException'类型的第一次机会异常 超时已过期。操作完成之前经过的超时时间或服务器没有响应。
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len) at System.Data.SqlClient.TdsParser.SkipValue(SqlMetaDataPriv md, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.SkipRow(_SqlMetaDataSet columns, Int32 startCol, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlDataReader.CleanPartialRead() at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean 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列时的某一行,但并非总是如此。查询返回的行数不到5万,有时它会通过所有行,有时只通过15k
答案 0 :(得分:0)
为什么不继续将SqlCommand实例的CommandTimeout属性设置为高数?这将使您的代码正常工作。
另一方面,您需要调试服务器这么长时间才能完成其工作。你不能从.NET方面做任何事情。您必须单步执行在SQL Server上执行的基础代码。
答案 1 :(得分:0)
每隔一次跑吗?你可能会分享一个命令吗? 如果您使用MARS并共享连接 - 请不要
using (SqlCommand cmd = con.CreateCommand)
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
}
}
答案 2 :(得分:0)
为什么要检查阅读器是否在while循环中关闭?
尝试使用using
确保正确处理问题。以下内容应该让一切顺利进行。
using (SqlConnection connection = MyDBConnection)
{
connection.Open();
SqlCommand command = new SqlCommand("SQL Query Here", connection) { CommandTimeout = 0 };
using (var reader = command.ExecuteReader())
{
try
{
while (reader.Read())
{
string test0 = reader[0].ToString();
string test1 = reader[1].ToString();
string test2 = reader[2].ToString();
string test3 = reader[3].ToString();
}
}
catch (Exception e)
{
//Make some Noise
}
}
}