1

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サイトがダウンするのを防ぐためです。

提案がありますか?

答えて

0

これは非常に簡単なADO実装を使用しており、正しく識別されているように、実際には接続プーリングや接続状態などを処理していません。

重いワークロードやエラーが蓄積しているようで、接続を適切に閉じることができないようです。 (これはあなたの "using"ステートメントが完了して処分するときに起こるはずです)。

最も簡単な解決策は、おそらくORM(個人的には私はDapperが好きですが、何でも選択してください。)を実行することですが、エラーを追加したり、再試行したりすることがあります。あなたのためにこのすべてのものを扱うためには最高のスーツ) - ホイールを再発明しようとするよりもずっと簡単で簡単です。

+0

他のプロジェクトでもDapperを使っていますが、ファンもあります。しかし、この場合は、そのコードにエラーをプッシュするだけで、役に立たないでしょう。また、Dapperは開いているConnectionでExecuteReaderを実行します。 { return cmd.ExecuteReader(GetBehavior(wasClosed、behavior)); } –

+0

個人的には、私は試してみたいと思いますが、どちらの方法でも、catchステートメントでConnection Disposalおよび/またはState Resetを実装するのが良い方法です。 –

関連する問題