私は自分のWebサイト(1日あたり20000〜600000)に多くのユーザーがいます。これはモバイルファイルのダウンロードサイトです。私は自分のサーバー(Windows Server 2008-R2)にリモートアクセスしています。
"サーバーが利用できません" エラーを以前に受信しましたが、現在は接続タイムアウトエラーが発生しています。
私はこれに精通していません - なぜそれが起こるのですか、そしてどのように私はそれを修正できますか?
完全なエラーは以下の通りです:
'/'アプリケーションでサーバーエラーが発生しました。タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。ステートメントは終了されました。説明:現在のWeb要求の実行中に未処理の例外が発生しました。エラーとコードのどこで発生したかの詳細については、スタックトレースを確認してください。
例外の詳細:System.Data.SqlClient.SqlException:タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。ステートメントは終了されました。
ソースエラー:
現在のWeb要求の実行中に未処理の例外が発生しました。例外の発生源と場所に関する情報は、以下の例外スタックトレースを使用して識別できます。
スタックトレース:
[SqlException(0x80131904):タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。ステートメントは終了されました。]
System.Data.SqlClient.SqlConnection.OnError(SqlException例外、ブール型breakConnection)+404
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()+412
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet、bulkCopyHandler、TdsParserStateObject stateObj)+1363
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds、RunBehavior runBehavior、String resetOptionsString)+6387741
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior runBehavior、ブールreturnStream、ブール非同期)+6389442
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Stringメソッド、DbAsyncResultの結果)+538
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult結果、Stringメソッド名、ブール値sendToPipe)+689
System.Data.SqlClient.SqlCommand.ExecuteNonQuery()+ 327
NovinMedia.Data.DbObject.RunProcedure(String storedProcName、IDataParameter []パラメータ、Int32&rowsAffected)+209
DataLayer.OnlineUsers.Update_SessionEnd_And_Online(Object Session_End、ブールオンライン)+440
NiceFileExplorer.Global.Application_Start(オブジェクト送信者、EventArgs e)+163[HttpException(0x80004005):タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。ステートメントは終了されました。]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContextコンテキスト、HttpApplicationアプリ)+4052053
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext、HttpContextコンテキスト、MethodInfo []ハンドラ)+191
System.Web.HttpApplication.InitSpecial(HttpApplicationState状態、MethodInfo []ハンドラ、IntPtr appContext、HttpContextコンテキスト)+352
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext、HttpContextコンテキスト)+407
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)+375[HttpException(0x80004005):タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。ステートメントは終了されました。]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context)+11686928 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContextコンテキスト)+141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerContext)
回答後に編集: Application_Start
内の私のGlobal.asax
は以下のようになります。
protected void Application_Start(object sender, EventArgs e)
{
Application["OnlineUsers"] = 0;
OnlineUsers.Update_SessionEnd_And_Online(
DateTime.Now,
false);
AddTask("DoStuff", 10);
}
呼び出されるストアドプロシージャは次のとおりです。
ALTER Procedure [dbo].[sp_OnlineUsers_Update_SessionEnd_And_Online]
@Session_End datetime,
@Online bit
As
Begin
Update OnlineUsers
SET
[Session_End] = @Session_End,
[Online] = @Online
End
オンラインユーザーを取得する方法は2つあります。
Application["OnlineUsers"] = 0;
を使うそのため、方法2では、すべてのOnlineUserをApplication_Start
にリセットします。そのテーブルには482,751レコード以上あります。
必要以上に時間がかかるクエリーがあるようです。あなたのスタックトレースとコードから、あなたはそれがどんなクエリであるかを正確に決定することができるはずです。
このタイプのタイムアウトには3つの原因があります。
デッドロックは修正が困難な場合がありますが、それが当てはまるかどうかを判断するのは簡単です。 Sql Server Management Studioを使ってデータベースに接続します。左側のペインでサーバーノードを右クリックし、 Activity Monitor を選択します。実行中のプロセスを見てください。通常、ほとんどがアイドル状態または実行中です。問題が発生すると、プロセス状態によってブロックされたプロセスを識別できます。プロセスを右クリックして details を選択すると、プロセスによって最後に実行されたクエリが表示されます。
2番目の問題により、データベースは最適とは言えないクエリプランを使用します。統計をクリアすることで解決できます。
exec sp_updatestats
それでもうまくいかない場合は、試してみることもできます
dbcc freeproccache
サーバに負荷がかかっているときは、最初に実行したときにすべてのストアドプロシージャとクエリが再コンパイルされるため、一時的に大きなパフォーマンスの低下を招くため、これを実行しないでください。しかし、この問題は 時々 が発生し、スタックトレースはアプリケーションが起動していることを示しているので、たまにしか実行されないクエリを実行していると思います。以前のクエリプランを再利用しないようにSQL Serverに強制することをお勧めします。そのやり方についての詳細は この答え を見てください。
3番目の問題については既に触れましたが、Sql Server Management Studioなどを使用して手動でクエリを実行することで、クエリのチューニングが必要かどうかを簡単に判断できます。統計情報をリセットした後でも、クエリの完了に時間がかかりすぎる場合は、おそらくそれを調整する必要があります。それを手助けするために、あなたは新しい質問で正確な質問を投稿するべきです。
ストアドプロシージャを実行するコードでは、次のようになります。
SqlCommand c = new SqlCommand(...)
//...
そのようなコード行を追加します。
c.CommandTimeout = 0;
これは、操作が完了するのに必要なだけ待機します。
SQLコマンドのCommandTimeout
プロパティを設定して、長時間実行されるSQLトランザクションを可能にすることができます。
タイムアウトの原因となっているSQLクエリも確認する必要があります。
これまでのすべての回答でこの問題が取り上げられていますが、すべてのケースを網羅しているわけではありません。
マイクロソフトはこの問題を認識し、サポートされているオペレーティングシステム用に2011年にそれを修正しています。
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)
.NETアセンブリを更新する必要があるかもしれません。
この問題はミラーデータベースの接続再試行アルゴリズムのエラーが原因で発生します。
再試行アルゴリズムが使用されると、データプロバイダーは最初の読み取り(SniReadSync)呼び出しが終了するのを待ちます。呼び出しはSQL Serverを実行しているバックエンドコンピューターに送信され、待機時間は接続タイムアウト値に0.08を掛けて計算されます。ただし、応答が遅い場合や、待機時間が経過する前に最初のSniReadSync呼び出しが完了していない場合、データプロバイダは接続を誤った運命の状態に設定します。
詳細はKB 2605597をご覧ください。
たぶんそれは誰かに役立つでしょう。私は同じ問題に直面し、私の場合、その理由はSqlConnectionが開かれていて、私が約2500回の繰り返しで呼び出したメソッドに配置されていなかったことです。接続プールが使い果たされました。適切に廃棄することで問題は解決しました。
私は3日頃同じ問題に取り組みました。私たちのレコード数はあまり多くないので、私たちの上級開発者は2つの画像と指紋をデータベースに保存しています。この16進値を取得しようとすると時間がかかりますが、プロシージャの実行にかかる平均時間は約38秒です。デフォルトのコマンドタイムアウトは30秒なので、ストアドプロシージャの実行に必要な平均時間よりも短くなります。コマンドタイムアウトを以下のように設定します。
cmd.CommandTimeout = 50
それでもうまくいきますが、クエリが50秒以上かかると、同じエラーが表示されることがあります。
CommandTimeout属性を設定する必要があります。 DbContext子クラスでCommandTimeout属性を設定できます。
public partial class StudentDatabaseEntities : DbContext
{
public StudentDatabaseEntities()
: base("name=StudentDatabaseEntities")
{
this.Database.CommandTimeout = 180;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<StudentDbTable> StudentDbTables { get; set; }
}
私は最近このエラーに遭遇し、少し調査した結果、データベースを保持しているディスクのスペースが不足している(1GB未満)ことが原因であることが判明しました。
データベースファイル(.mdfと.ldf)を同じサーバー上の別のディスク(より多くのスペースを持つ)に移動するとすぐに、タイムアウトした同じページ(クエリを実行している)が3秒以内に読み込まれました。
このエラーを解決しようとしている間に調査するもう1つの事柄はデータベースログファイルのサイズです。ログファイルを縮小する必要があるかもしれません。
Sp_fooでの計算に時間がかかる問題がありますので修正しました
このちょっとしたコードで
public partial class FooEntities : DbContext
{
public FooEntities()
: base("name=FooEntities")
{
this.Configuration.LazyLoadingEnabled = false;
// Get the ObjectContext related to this DbContext
var objectContext = (this as IObjectContextAdapter).ObjectContext;
// Sets the command timeout for all the commands
objectContext.CommandTimeout = 380;
}
@SilverLight ..これは明らかにDatabaseオブジェクトに関する問題です。それは、よく書かれていないクエリ、または欠けているインデックスかもしれません。しかし現時点では、データベースオブジェクトに関する問題を調査せずにタイムアウトを増やすことをお勧めしません。
NovinMedia.Data.DbObject.RunProcedure(String storedProcName, IDataParameter[] parameters, Int32& rowsAffected) +209
このコード行にブレークポイントを置いてプロシージャ名を見つけ、その実行計画を見てプロシージャを最適化します。
ストアード・プロシージャーに関する詳細を投稿するまで、私はあなたをもっと助けることはできません。
やってみる
EXEC SP_CONFIGURE 'remote query timeout', 1800
reconfigure
EXEC sp_configure
EXEC SP_CONFIGURE 'show advanced options', 1
reconfigure
EXEC sp_configure
EXEC SP_CONFIGURE 'remote query timeout', 1800
reconfigure
EXEC sp_configure
次にインデックスを再構築します
TLDR:
さまざまな理由でこのエラーが頻繁に発生し、次のようなさまざまな解決策があります。
SqlCommand.CommandTimeoutプロパティで設定した時間よりもSQLクエリに時間がかかるため、タイムアウトになりました。
明らかに、この問題を解決するためにCommandTimeoutを増やすことができますが、その前にインデックスを追加してクエリを最適化する必要があります。 Sql server management studio - を含む 実際の実行計画 その後 Sql server management studio でクエリを実行すると、適切なインデックスが提示されます。ほとんどの場合、クエリを最適化できれば、タイムアウトの問題を解消できます。
デフォルトのタイムアウトは15秒です、それを変更するには、0は無制限、他の数値は秒数です。
コード内
using (SqlCommand sqlCmd = new SqlCommand(sqlQueryString, sqlConnection))
{
sqlCmd.CommandTimeout = 0; // 0 = give it as much time as it needs to complete
...
}
あなたのWeb.Configでは、「コマンドタイムアウト= 0」。タイムアウトしない、または1時間(3600秒)以下にする
<add name="ConnectionString" connectionString="Data Source=ServerName;User ID=UserName;Password=Password;Command Timeout=3600;" providerName="System.Data.SqlClient" />
また、保留中のトランザクションがないことを確認してください。 :)
私はいくつかのテストを行い、安全のためにトランザクションを開始しましたが、決してクローズしませんでした。エラーがより明確になったらよかったのですが、まあまあです!