与SqlDataReader打了一个加重的错误。此旧代码在运行Windows Server 2012的AWS服务器上使用.NET Framework 3.5在Visual Basic中。数据库是在Amazon的RDS环境中运行的Msft Sql Server。
我们在日志中开始看到此错误:
“超时已过期。在操作完成之前已经过了超时时间,或者服务器没有响应。”
并且错误堆栈中的最后一个条目是:
at System.Data.SqlClient.SqlCommand.ExecuteReader()
以下是我们的db包装器中发生错误的代码。
Try
Using connection As New SqlConnection(dbConnStr)
connection.Open()
Using command As New SqlCommand(sql, connection)
Using dataReader As SqlDataReader = command.ExecuteReader()
Do While dataReader.Read()
'do stuff with the results here
Loop
End Using
End Using
End Using
Catch
'write error to log here
End Try
我添加了一些额外的日志记录,我学到的一件事是connection.state =在调用ExecuteReader之前打开,而在发生错误之后就关闭了。
为了缓解我在某些重试逻辑中构建的问题。如果ExecuteReader没有运行,我会拯救,等待一秒钟,然后再次调用它。这种方法每次都有效,但会引入30秒的延迟。我可能会将commandTimeout降低到比30秒更烦人的事情,但我真的很感兴趣为什么错误发生在第一位。
我决定的一件事是连接池处理是艺术而不是科学。在这种情况下,我们的结论是与数据库的连接以某种方式变得腐败。我们推测新的连接生命周期设置有助于回收池并防止它爆炸,这很好,因为它可以防止这个网站崩溃。
有什么建议吗?
答案 0 :(得分:0)
这使用了一个非常简单的ADO实现,正如您所正确识别的那样,它有时并不能真正处理连接池,连接状态等。
听起来好像繁重的工作量或错误正在累积,它无法正确关闭连接。 (这应该在您的“使用”声明完成并处置时发生)。您可以阅读有关添加更多错误/重试处理失败,关闭然后重新打开失败的连接状态等的信息。
最简单的解决方案可能是实现一个ORM(我个人喜欢Dapper,但选择最适合你的东西)来处理所有这些东西 - 它可能比尝试重新发明更好更容易轮。