MSSQLSERVER_3617

適用対象:SQL Server

詳細

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

説明

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

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

ユーザーの操作

原因の概要:

  • クエリが、想定期間内 (構成されたクエリ タイムアウト値より小さい) に確実に完了するようにする
  • クエリまたはコマンドのタイムアウト値を大きくする
  • ユーザーがクエリの実行を手動で取り消したどうかを確認する
  • アプリケーションまたは OS が予期せず終了したかどうかを確認する

クエリが、想定期間内 (構成されたクエリ タイムアウト値より小さい) に確実に完了するようにする: Attention イベントが発生する最も一般的な理由は、クエリ タイムアウト値を超えた結果、アプリケーションによってクエリが自動的に終了されることにあります。 クエリまたはコマンドのタイムアウト値が 30 秒に設定されていて、クエリからクライアント アプリケーションに、データのパケットが 1 つも返されない場合、クライアント アプリケーションによってクエリは取り消されます。 このような場合は、クエリに時間がかかる理由を把握し、その期間を短縮するために適切な手順を実施することが最適な方法です。

クエリまたはコマンドのタイムアウト値を大きくする: 取り消されたクエリが事前に規定されたベースライン期間内に実行されるようにしても、コマンドのタイムアウトに達する場合は、データベース アプリケーションのタイムアウト値を大きくすることを検討してください。

ユーザーがクエリの実行を手動で取り消したどうかを確認する: 場合によっては、ユーザーがクエリを取り消したという理由だけで、Attention イベントが発生する可能性があります。 このような場合、ユーザーの期待値がクエリの実際の速度を超えているかどうかを確認した上で、クエリを調整するか、期待されるベースラインを文書化することで、それらに対処することが賢明と考えられます。

アプリケーションまたは OS がクエリまたは接続を予期せず終了したのかどうか、あるいはアプリケーション自体が終了したのかどうかを確認する: 状況を調査して、アプリケーション側で何が起こっているかを理解します。 アプリケーション ログまたはシステム ログを調べると、考えられる根本原因の手掛かりが得られることがあります。

Attention とトランザクション

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

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

  • より一般的には、アプリケーションでは 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);
        }
    }
}