次の方法で共有


MSSQLSERVER_3617

適用対象:SQL Server

詳細

属性
製品名 SQL Server
イベント ID 3617
イベント ソース MSSQLSERVER
コンポーネント SQLEngine
シンボル名 SYS_ATTN
メッセージ テキスト

説明

エラー 3617 は、実行途中のクエリがアプリケーションまたはユーザーによって取り消された場合、あるいは接続が切断された場合に発生します。 このクエリ取り消しがアプリケーションによって行われると、データベース エンジン内で Attention イベントが発生します。 アテンション イベントは、クエリの実行を終了するクライアント アプリケーションの要求を登録する SQL Server イベントです。 拡張イベントまたは SQL トレース Attention イベント クラスを使用して、SQL Server 側でアテンション イベントをトレースできます。 Attention は内部的にエラー 3617 として表示されます。

注意 (クエリの取り消し) は、SQL Server によって処理最も一般的なTDS イベントの 1 つです。 クエリの取り消し要求が届くと、セッションまたは要求に対して Attention ビットが設定されます。 セッションで呼び出しポイントが処理されると、Attention が取得され、受け入れられます。 Attention と、それが他のコンポーネントとどのような相互関係にあるかについて詳しくは、タスク、ワーカー、スレッド、スケジューラー、セッション、接続、リクエストと、その意味に関するページを参照してください。

ユーザー アクション

原因の概要:

原因 Description
予想される期間内にクエリが完了していることを確認する (構成されたクエリ タイムアウト値より小さい) アテンション イベントの最も一般的な理由は、クエリタイムアウト値を超えたために、アプリケーションによってクエリが自動的に終了することです。 クエリ/コマンドのタイムアウト値が 30 秒に設定されていて、クエリが 1 パケットのデータをクライアント アプリケーションに返さない場合、後者はクエリをキャンセルします。 このような場合は、クエリに時間がかかる理由を把握し、その期間を短縮するために適切な手順を実施することが最適な方法です。
クエリまたはコマンドのタイムアウトを増やす キャンセルされたクエリが、事前に確立されたベースライン期間内に実行されているが、コマンド のタイムアウトに達した場合は、データベース アプリケーションのタイムアウト値を増やすことを検討してください。
ユーザーがクエリの実行を手動でキャンセルしたかどうかを確認する 場合によっては、ユーザーがクエリを取り消したために、アテンション イベントが発生することがあります。 このような場合は、ユーザーの期待値がクエリの実際の速度を超えているかどうかを確認し、クエリをチューニングするか、予想されるベースラインを文書化することによって、それに対処することが賢明な場合があります。
アプリケーションまたは OS がクエリまたは接続を予期せず終了したかどうか、またはアプリケーション自体が終了したかどうかを調べる 状況を調査して、アプリケーション側で何が起こるかを理解します。 アプリケーション ログまたはシステム ログを調べると、考えられる根本原因に関する手掛かりが得られます。

注意とトランザクション

一般には、アプリケーションがクエリ タイムアウトに達し、クエリを取り消したときに、Attention イベントが発生します。 アテンション イベントが発生しても、SQL Server は開いているトランザクションを自動的にロールバックしません。 トランザクションをロールバックするのはアプリケーションの役割であり、一般的な処理方法として次の 2 通りがあります。

  • SQL Server に接続するときに SET XACT_ABORT を有効にして、トランザクションのロールバックを制御します。 アプリケーションでこれを行わないと、孤立したトランザクションが発生します。

  • より一般的には、アプリケーションでは try.. catch... finally を使用してエラーが処理されます。 try ブロックでトランザクションを開き、エラーが発生した場合は、catch ブロックまたは finally ブロックでトランザクションをロールバックします。

次に例を示します。

using (SqlConnection connection = new SqlConnection(sqlConnectionString))
{
    SqlTransaction transaction;
    SqlCommand command = connection.CreateCommand();

    connection.Open();
    transaction = connection.BeginTransaction("UpdateTran_Routine1");

    command.Connection = connection;
    command.Transaction = transaction;

    try
    {
        //update one of the tables
        command.CommandText = "update dl_tab1 set col1 = 987";
        command.ExecuteNonQuery();
        transaction.Commit();
    }

    catch (SqlException ex)
    {
        // Attempt to roll back the transaction.
        try
        {
            transaction.Rollback();
        }
        catch (Exception ex2)
        {
            // This catch block will handle any errors that may have occurred
            // on the server that would cause the rollback to fail, such as
            // a closed connection.
            Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
            Console.WriteLine("  Message: {0}", ex2.Message);
        }
    }
}