SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Server 側でエラーを取得するための方法

without comments

以前、次の投稿を書きました。

これらの投稿では、「アプリケーションからのクエリタイムアウト (コマンドタイムアウト)」を SQL Server 側 (DB サーバーサイド) で取得する方法について記載を行いました。
(本ブログでも何回か書いていますが、クエリのタイムアウトは「アプリケーションから発行された Attention のメッセージにより、SQL Server がクエリをキャンセルする処理」ですので、クエリをタイムアウトさせているのは、SQL Server ではなく、クエリを発行したアプリケーション側の処理となります)

SQL Server に対してクエリを実行する際に発生するのは、クエリタイムアウトだけでなく、様々なエラーがあります。

本投稿では、クエリタイムアウト以外のエラーを SQL Server 側で取得する方法の一例について紹介したいと思います。

クエリのタイムアウトや、クエリの実行の失敗については、クエリ実行側 (アプリケーション側) で取得した方が正確かと思いますので、SQL Server で全てをキャッチするのではなくアプリケーション (または、APM のような仕組み) でエラーを把握した方が良いと思います。
(DB に対してのクエリ実行でエラーが発生すると、SQL Server 側の調査のみで原因を特定してくれという依頼が多いのですよね…。)

 

SQL Server 側でエラーを検知するためには次のような方法を用いることができます。

では、それぞれについて、どのような情報が取得できるのかを見ていきましょう。

 

SQL Server:SQL Errors オブジェクト

SQL Server:SQL Errors オブジェクトはパフォーマンスモニターの情報となります。

image

ドキュメントに記載されていますが、次のような情報を時系列データとして取得することができます。

image

 

この中で、よく確認を行うのは「User Erros」の項目です。

SQL Server のエラーについては、重大度 (Sevirity) が設定されており、重大度については、データベース エンジン エラーの重大度 に記載されています。

image

通常、目にする機会があるのは、1~16 あたりまでになるかと。

SQL Server:SQL Errors オブジェクト では、いくつかのカテゴリでエラーを確認することができますが、

  • 重大度 10 まで : Info Errors
  • 重大度 11 以上 : User Errors

というような分け方が大きなくくりになるかと思います。

SQL Server で明示的にエラーを発生させる際には、RAISERROR を使用することができます。

RAISERROR ('TEST',10,0)

 

このようなクエリで明示的にエラーを発生させることができます。

上記の場合は、重大度レベル : 10 で実行をしていますので、このようなエラーの場合は「Info Erros」となります。

数値を 11 以上に変更すると「User Erros」として計上されることが確認できるかと。

基本的には「重大度レベル 11 以上の User Erros」に注視して、SQL Server のエラーの発生状況を確認することになります。

 

User Error Message イベント クラス

SQL Server:SQL Errors オブジェクト でエラーの発生状況を取得することができました。

次に確認したくなるのは「実際にどのようなエラーが発生したのか?」の情報ではないでしょうか。

エラーの詳細な情報を取得する場合には、拡張イベントUser Error Message イベント クラス となります。

拡張イベントの「error_reported」が上記のイベント相当となりますので、この情報の取得を行います。

image

全てのエラーを取得するとノイズが混じってしまいますので、重大度 (Sevirity) については 11 以上でフィルターしておいた方が良いです。

image

接続文字列や、エラーの内容によっては、「どのアプリケーションの、どのクエリなのか?」が取得できる可能性がありますので、グローバル フィールド (アクション) としては、「client_app_name」と「sql_text」は追加で取得しておいた方が良いかと。

image

このような拡張イベントを設定しておくことで、エラーが発生した際には、次のようなログを取得することができますので、どのようなエラーが発生していたかの詳細を確認することができます。

image

 

エラーメッセージを確認

今回、重大度レベル 11 以上を重点的に取得していますが、SQL Server に発生するエラーにどのようなものが存在するかについては、メッセージ (エラー用) のカタログ ビュー – sys.messages から確認することができます。

各言語用のメッセージが登録されていますので、日本語メッセージであれば、次のようなクエリで取得できます。

SELECT * FROM sys.messages
WHERE language_id = 1041 AND severity >= 11
ORDER BY severity ASC, message_id ASC

 

稀に確認するのが次のようなクエリの実行結果ですね。

SELECT * FROM sys.messages
WHERE language_id = 1041 AND severity >= 16
AND text LIKE '%スキーマ%変更%'
ORDER BY severity ASC, message_id ASC

 

スキーマに変更を行った場合、どのようなエラーが発生する可能性があるのかを登録されているメッセージから取得しています。

スキーマ変更に関してはいくつかのメッセージが登録されているのですが、次のようなメッセージの存在を確認することができます。

  • 対象になるテーブルが作成された後にスキーマが変更されました。SELECT INTO クエリを再実行してください。
  • ストアド プロシージャが対象テーブルのスキーマを変更したので、INSERT EXEC が失敗しました。
  • 挿入先テーブルのスキーマ変更により、一括挿入に失敗しました。
  • カーソルが宣言された後にテーブル スキーマが変更されたので、カーソル操作を完了できませんでした。

エラーメッセージから、スキーマを変更することにより影響を受ける可能性のある操作を把握することができますね。

 

SQL Server に対してクエリを実行した際の失敗の情報を「SQL Server 観点ですべて調査を行う」のは現実的ではないので、発行元のアプリケーションの観点でも情報を取得するのが一番良いのですが、SQL Server 側でエラーを確認するための仕組みとしては、これらの方法を覚えておくと役に立つのではないでしょうか。

Written by Masayuki.Ozawa

6月 18th, 2020 at 11:04 pm

Posted in SQL Server

Tagged with

Leave a Reply