1. ホーム
  2. c#

[解決済み] タイムアウトが発生しました。操作の完了前にタイムアウトが発生したか、サーバーが応答していない。ステートメントが終了しました

2022-03-12 06:18:21

質問内容

私のウェブサイトは携帯ファイルのダウンロードサイトですが、多くのユーザー(1日2万~6万人)が利用しています。 サーバー(Windowsサーバー2008-R2)にはリモートでアクセスできます。
受信した サーバは使用できません。 というエラーが出ていたのですが、今は接続タイムアウトエラーが表示されています。
私はこのことについてよく知らないのですが、なぜこのようなことが起こるのでしょうか、またどのように修正すればよいのでしょうか。

エラーの全容は以下の通りです。

アプリケーション '/' でサーバーエラーが発生しました。タイムアウトが切れました。 タイムアウト時間 操作の完了前に経過したか、サーバーが停止しています。 が応答しています。文は終了しました。説明 この文は 現在のWebの実行中に処理されない例外が発生しました。 リクエストに対応します。スタックトレースをご覧ください。 というエラーが発生しました。

例外の詳細です。System.Data.SqlClient.SqlException: タイムアウト が失効しました。 完了する前にタイムアウト時間が経過しました。 操作に失敗したか、サーバーが応答していません。ステートメントは を終了した。

ソースエラーです。

の実行中に処理されない例外が発生しました。 現在の Web リクエスト。リクエストの送信元と送信先に関する情報 例外は、以下の例外スタックトレースで確認することができます。

スタックトレース

[SqlException (0x80131904)。タイムアウトが切れました。 タイムアウト時間 操作の完了前に経過したか、サーバーが停止しています。 が応答しています。ステートメントは終了しました]。
System.Data.SqlClient.SqlConnection.OnError(SqlException exception.OnError.OnError) ブール breakConnection) +404
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior.RunBehavior.RunBehavior.RunBehavior.RunBehavior.RunBehavior) SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1363
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds.SqlCommand.FinishExecuteReader), RunBehavior runBehavior, String resetOptionsString) +6387741
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior) cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean 非同期) +6389442
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior) cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String メソッド, DbAsyncResult result) +538
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult) result, String methodName, Boolean sendToPipe) +689
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +327
NovinMedia.Data.DbObject.RunProcedure(String storedProcName.DbObject.RunProcedure), IDataParameter[] parameters, Int32& rowsAffected) +209
DataLayer.OnlineUsers.Update_SessionEnd_And_Online(Object Session_End, ブールオンライン) +440
NiceFileExplorer.Global.Application_Start(Object sender, EventArgs e) +163

[HttpException (0x80004005)。タイムアウトが発生しました。 タイムアウト時間 操作の完了前に経過したか、サーバーが停止しています。 が応答しています。ステートメントは終了しました]。
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +4052053
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +191
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context). +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 context) +141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +4863749


は、回答後に編集してください。
我が Application_StartGlobal.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つあるんです。

  1. 使用 Application["OnlineUsers"] = 0;
  2. もうひとつはデータベースを使ったもの

そこで、2番目の方法として、すべてのOnlineUsersを Application_Start . そのテーブルには、482,751件以上のレコードがあります。

どのように解決するのですか?

必要以上に時間がかかっているクエリがあるようです。 スタックトレースとコードから、どのようなクエリであるかを正確に判断することができるはずです。

このタイプのタイムアウトには、3つの原因が考えられます。

  1. どこかでデッドロックが発生している
  2. データベースの統計情報、またはクエリプランキャッシュが不正です。
  3. クエリが複雑すぎるため、チューニングが必要です。

デッドロックは解決が難しい場合もありますが、そうであるかどうかを判断するのは簡単です。Sql Server Management Studio でデータベースに接続します。左側のペインでサーバーノードを右クリックし、次の項目を選択します。 アクティビティモニタ . 実行中のプロセスを見てみましょう。 通常、ほとんどはアイドル状態か実行中です。問題が発生した場合、ブロックされているプロセスをプロセスの状態によって特定することができます。プロセスの上で右クリックし 詳細 そのプロセスで最後に実行されたクエリが表示されます。

2つ目の問題は、データベースが最適でないクエリプランを使用する原因となります。これは、統計情報をクリアすることで解決できます。

exec sp_updatestats

うまくいかない場合は、次のようにすることもできます。

dbcc freeproccache

なぜなら、すべてのストアドプロックとクエリが最初に実行されるときに再コンパイルされるため、一時的に大きなパフォーマンスヒットが発生するからです。 しかし、この問題が発生するのは 時々 スタックトレースでは、アプリケーションは起動しているようなので、時々しか実行されないクエリを実行しているのだと思います。SQL Server が以前のクエリプランを再利用しないように強制する方がよいかもしれません。参照 この回答 をクリックすると、その方法の詳細が表示されます。

3つ目の問題についてはすでに触れましたが、クエリのチューニングが必要かどうかは、Sql Server Management Studioなどを使って手動でクエリを実行することで簡単に判断することができます。統計情報をリセットしても、クエリの完了に時間がかかりすぎる場合は、おそらくチューニングが必要です。そのような場合は、新しい質問で正確なクエリを投稿してください。