SqlDataReaderで悪化しているバグと戦っています。この古いコードは、Windows Server 2012を実行しているAWSサーバーで.NET Framework 3.5を使用してVisual Basicにあります。データベースはAmazonのRDS環境で実行されているMsft SQL Serverです。 SqlDataReaderタイムアウト期限切れの奇数エラー
私たちは、ログにこのエラーを見て開始しました:「。タイムアウトの期限が切れ、タイムアウト期間が操作またはサーバーが応答していないが完了する前に経過し、」とエラー・スタック内の最後のエントリは次のとおりです。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
- このシステムの背後にあるデータベースには、間違いなく働いています。私はトレースを実行し、呼び出されているクエリのトンを参照してください。 フィルタを使用してトレースを実行して、約5秒間のクエリのみを表示し、存在しない。
- エラーをトリガするクエリはランダムであり、決して同じではありません。そして、エラーが表示されたら、ログからクエリを取得して を手動で実行し、すぐに正常に実行されます。
- トレースは、クエリがデータベースで実行されないことを示します。
- AWSで動作しているので、別のサーバをスピンアップしてAMIを復元して同じ問題が発生しました。
- エラーが累積すると、接続プールが爆発します。私たちの接続プールは700に設定されています。接続文字列にこの接続 Lifetime = 30を追加しました。これはプールを 100のままにしています。
- 何千ものクエリがエラーの間に正常に実行されます。
- Windowsと.NETの両方が最新の状態にパッチされています。
私はいくつかの余分なログインをしてしまいました.1つは、Connection.state = ExecuteReaderの呼び出しの直前に開き、エラーが発生した直後に閉じたことです。
問題を軽減するために、私はいくつかのリトライロジックを組み込みました。 ExecuteReaderが実行されない場合、私は救済し、1秒待ってからもう一度呼び出します。これは毎回動作しますが、30秒の遅延が発生します。私はおそらくcommandTimeoutを30秒よりも厄介なものに落とすことができますが、最初にエラーが発生している理由に本当に関心があります。
私が決めたことの1つは、接続プールの処理が科学ではなく芸術であることです。この場合、私たちの結論は、データベースへの接続が何らかの形で壊れているということです。プールのリサイクルに役立つ新しいConnection Lifetime設定を推測し、プールが爆発するのを防ぎます。これは、このWebサイトがダウンするのを防ぐためです。
提案がありますか?
他のプロジェクトでもDapperを使っていますが、ファンもあります。しかし、この場合は、そのコードにエラーをプッシュするだけで、役に立たないでしょう。また、Dapperは開いているConnectionでExecuteReaderを実行します。 { return cmd.ExecuteReader(GetBehavior(wasClosed、behavior)); } –
個人的には、私は試してみたいと思いますが、どちらの方法でも、catchステートメントでConnection Disposalおよび/またはState Resetを実装するのが良い方法です。 –