25

私は、VS 2010 (.NET 4.0) で開発したマルチスレッド Windows サービスを持っています。これは、数個から数十個のスレッドを持つことができ、それぞれがインターネット経由で低速サーバーからデータを取得し、ローカル データベースを使用してこれを記録します。データ (つまり、プロセスは LAN や CPU バウンドではなく、インターネット バウンドです)。

ある程度の規則性で、複数のスレッドから同時に次のエラーの洪水/突風/バーストが発生しています。

System.Data.SqlClient.SqlException (0x80131904): タイムアウトが発生しました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。

通常、このエラーのコール スタックは次のとおりです。

System.Data.ProviderBase.DbConnectionPool.GetConnection (DbConnection owningObject) で

System.Data.ProviderBase.DbConnectionFactory.GetConnection (DbConnection owningConnection) で

System.Data.ProviderBase.DbConnectionClosed.OpenConnection (DbConnection outerConnection、DbConnectionFactory connectionFactory) で

System.Data.SqlClient.SqlConnection.Open() で

接続文字列で接続タイムアウトを指定していません。このデータベースで動作している他のアプリケーションとプロセスがあります。この種の行動に出くわした人はいますか?もしそうなら、それを防ぐために何が行われましたか?

私のデータ アクセス レイヤーで最も一般的に呼び出されるメソッドは次のようになります。他のすべての DAL メソッドは同じアプローチに従います。

using (SqlConnection con = new SqlConnection(GetConnectionString()))
using (SqlCommand cmd = new SqlCommand("AddGdsMonitorLogEntry", con))
{
    cmd.CommandType = CommandType.StoredProcedure;

    /* setting cmd.Parameters [snipped] */

    // We have been getting some timeouts writing to the log; wait a little longer than the default.
    cmd.CommandTimeout *= 4;

    con.Open();

    cmd.ExecuteNonQuery();
}

どうもありがとう!

編集

ミラーリングされた環境でこれが発生することについてのコメントを考えると、問題のデータベースがミラーリングされていることに言及する必要があります。SSMS では、「自動フェールオーバーなしの高安全性 (同期)」モードで、「プリンシパル、同期済み」としてマークされています。

2011 年 5 月 26 日編集

SQL Server ログに問題を示すものは何も表示されません。(私はそのサーバーの Windows イベント ビューアにアクセスできませんが、誰かに探してもらいました。)

4

5 に答える 5

15

今日作成されたばかりのMSDN ブログの投稿によると(Google 万歳!):

マイクロソフトは、これが ADO​​.NET の現在のリリースの問題であることを確認しています。この問題は、Visual Studio 2011 に同梱されている ADO.NET バージョンで修正される予定です。

当面の間、次の回避策をご利用ください。

  1. 接続文字列のタイムアウトを 150 秒に増やします。これにより、最初の試行で接続するのに十分な時間が与えられます (150* .08=12 秒)。

  2. 接続文字列に MinPool Size=20 を追加します。これにより、プール内で常に最低 20 の接続が維持され、新しい接続が作成される可能性が少なくなるため、このエラーの可能性が減少します。

  3. ネットワークのパフォーマンスを向上させます。NIC ドライバーを最新のファームウェア バージョンに更新します。NIC カードが特定の Scalable Networking Pack 設定と互換性がない場合、ネットワーク遅延が発生することが確認されています。Windows Vista SP1 以降を使用している場合は、Receive Window Auto-Tuning を無効にすることも検討してください。NIC チーミングを有効にしている場合は、無効にすることをお勧めします。

投稿自体は興味深い読み物で、TCP/IP 接続再試行アルゴリズムについて語っています。そして、「これはミラーリングに関連しているように見えます...」と言ったすべての人々に称賛を!これについてのコメントは、「SQL Server からの応答が遅いため、またはネットワークの遅延が原因である」ことに注意してください。

うーん!!!

投稿してくれたみんなに感謝します。Visual Studio 11 を待つ (そして購入する) 必要はありません。

于 2011-05-26T21:24:11.397 に答える
7

接続タイムアウトは、コマンド タイムアウトとは別のものです。コマンド タイムアウトは、接続が確立されている状況に適用されますが、内部的な理由により、サーバーが必要な時間内に結果を返すことができません。デフォルトのコマンド タイムアウトは 30 秒です。 http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx

接続文字列で接続タイムアウトを指定してみてください。デフォルト値は 15 秒で、これが問題の原因である可能性があります。コードで接続タイムアウトを指定することもできます: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectiontimeout.aspx

于 2011-05-15T14:02:29.710 に答える
1

私たちが持っているこの古いデータベースサーバーで時々これを取得します(現在10歳になっています)。それが起こるのは、何かが接続/クエリでそのことを絶えず叩いているからです。私の推測では、それが発生した場合、データベース サーバーに負荷がかかっている (または接続数が多いなど) ことがわかると思います。とにかく、私の経験では、コードを最適化し、データベースを最適化し、データベースサーバーなど、すべて役立ちます。Piotr が提案するもう 1 つの方法は、単純に接続のタイムアウトを増やすことです。それでも、いくつかのことを調べて最適化します(長期的には役立つはずです)。

于 2011-05-20T14:09:10.500 に答える
0

リモート サーバーで実行しているクエリを最適化すると、常に役立ちます。各クエリの時間を計って、実行時間の長いクエリを探します。読み取りのみを行っている場合は、SELECT ステートメントで(NOLOCK)ヒントを使用します。これは私にとって命の恩人でした。それを読んで、アプリケーションに適していることを確認してください。リモート データベースにアクセスできる場合は、インデックスが断片化されていないことを確認してください。これにより、クエリの実行が大幅に遅くなります。SQL メンテナンス プランの一環として、インデックスが再構築/再編成されていることを確認します。必要に応じて新しいインデックスを追加します。

タイムアウトを延長すると、事態が悪化する可能性があります。クエリをそれよりも長く実行すると、より多くのクエリがタイムアウトになる可能性があります。タイムアウトは、サーバーとそれにアクセスする他のクライアントを保護するためにあります。それを少し上げるのは大したことではありませんが、クエリを長時間実行してサーバーを停止させたくありません。

于 2011-05-20T15:30:34.087 に答える
0

この問題をある程度確実に再現することができました。処理ジョブが要求されると、新しいアプリドメイン/スレッドで処理を開始するサービスがあります。このスレッドは、10 ~ 16 のデータベース クエリを同時に実行します。これらのジョブを 30 個ずつ実行すると、ランダムに 1 つまたは 2 つのジョブがタイムアウト エラーでクラッシュします。

接続文字列を変更して、Pooling=false で接続プールをオフにすると、エラーが次のように変わりました。接続は Parallel.For 内で発生しているため、これは集計例外内で 3 回または 4 回スローされます。

System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   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.TdsParser.ConsumePreLoginHandshake(Boolean encrypt, Boolean trustServerCert, Boolean& marsCapable)
   at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginWithFailover(Boolean useFailoverHost, ServerInfo primaryServerInfo, String failoverHost, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at Tps.PowerTools.CoreEngine.V5.DataAccess.DataContext.ExecuteQuery(PtQuery query, ValueStore`1 store, String readerDescription) in C:\SourceCode\Tps.PowerToolsV1\Trunk\Libraries\CoreEngine\CoreEngine.V5\DataAccess\DataContext.cs:line 326
   at Tps.PowerTools.CoreEngine.V5.DataAccess.DataContext.<StockHistoricalData>b__15(PtQuery query) in C:\SourceCode\Tps.PowerToolsV1\Trunk\Libraries\CoreEngine\CoreEngine.V5\DataAccess\DataContext.cs:line 302
   at System.Threading.Tasks.Parallel.<>c__DisplayClass32`2.<PartitionerForEachWorker>b__30()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass7.<ExecuteSelfReplicating>b__6(Object )
于 2011-05-15T21:38:53.563 に答える