一直在与SqlDataReader争斗加重的错误。此旧代码位于运行Windows Server 2012的AWS服务器上使用.NET Framework 3.5的Visual Basic中。数据库是在Amazon RDS环境中运行的Msft Sql Server。SqlDataReader超时过期奇怪的错误
我们开始在我们的日志看到此错误:“超时时间已超时周期之前的操作或服务器没有响应的完成经过”
并在错误堆栈中的最后一项是:
在System.Data.SqlClient.SqlCommand.ExecuteReader()
这里是我们的分贝包装发生错误的代码。
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
- 这个系统背后的数据库肯定是正在制定。我跑了一丝,看到大量的查询被调用。还用 过滤器跟踪了大约5秒的查询,但没有。
- 触发错误的查询是随机的,从不相同。当我看到错误时,我可以从日志中获取查询并手动运行 ,并且它可以快速/成功运行。
- 该跟踪还表示该查询从未在数据库中运行。
- 由于我们在AWS运行,我们创建了另一台服务器并将AMI恢复到它,并得到同样的问题。
- 错误开始积累后,我们的连接池就会爆炸。我们的连接池设置为700.我们确实将连接 Lifetime = 30添加到了我们的连接字符串,并将该池保持在 附近。
- 我会看到数千个查询在错误之间成功运行。
- Windows和.NET都修补为最新。
我坚持一些额外的登录,我学到的一件事情是connection.state =就在调用ExecuteReader之前打开,并在错误发生之后关闭。
为了缓解我建立在一些重试逻辑的问题。如果ExecuteReader没有运行,我就纾解,等一秒钟,然后再次调用它。这每次都有效,但会延迟30秒。我可能会将commandTimeout降到30秒以下,但我真的很感兴趣为什么错误首先发生。
我决定的一件事是连接池处理是艺术而不是科学。在这种情况下,我们的结论是与数据库的连接已经以某种方式变得腐败。我们推测新的连接生命周期设置有助于回收池并防止池爆炸,这很好,因为它可以防止本网站停机。
有什么建议吗?
我在其他项目中也使用过Dapper,也是粉丝。但在这种情况下,它只会将错误推送到该代码中,这无济于事。 Dapper还在打开的Connection上执行ExecuteReader: {0}返回cmd.ExecuteReader(GetBehavior(wasClosed,behavior)); } –
我个人倾向于尝试,但无论哪种方式,一个好的第一步可能是在catch语句中实现连接处理和/或重置状态。 –