SQL Server 2016 以降 / SQL Database で利用することができるクエリストアでは、実行されたクエリの種類を、
query_store_runtime_stats から、次のような内容で判断することができます。
アプリケーションから実行されたクエリの状態が、クエリストア上で通常実行として認識される状態の理解が少し足りていなくて、調べたので本ブログでもまとめておこうと思います。
クエリストアでは、冒頭で紹介した 3 種類の内容でクエリの実行状態を判断することができます。
これらの状態については「SQL Sever に対してクエリを実行することができたか?」というのが一つの判断となっているようです。
- クエリのコマンドタイムアウト
- クエリの強制終了
- キー重複によるエラー
というようなケースに関しては「SQL Server に対してクエリ実行が行えている」状態で発生する事象となりますので、これらのクエリについては、実行状態に合わせてクエリストアに情報が格納されますので、エラーの状態をクエリストアから分析することができます。
しかし、「SQL Server にクエリの実行を行うことができたがキャンセルされた」というような状態については、クエリストア場が「通常実行」として情報が格納されているようです。
「SQL Server にクエリの実行を行うことができたがキャンセルされた」という状態ですが、「トランザクションをロールバック」した状態などが該当します。
トランザクション内のクエリ自体がエラーとなっているのであれば、クエリストアとしては「Aborted」として格納されていますので、エラーが発生したクエリとして確認を行うことができます。
しかし、トランザクション内のクエリは正常に完了していて、最終的な処理としてロールバックされた場合 (論理的な整合性を合わせる目的等でロールバックした場合) は、クエリストアとしては「通常実行」として情報が取得されているようです。
適当ですが、次の用なクエリの実行を行ってみます。
$con = New-Object System.Data.SqlClient.SqlConnection("xxxxxxxxxxxxxxx") $con.Open() try{ $tran = $con.BeginTransaction() $cmd = $con.CreateCommand() $cmd.Transaction = $tran $cmd.CommandText = "INSERT INTO T1 (C1) VALUES(10)" $cmd.ExecuteNonQuery() throw "TEST Exception" $tran.Commit() }catch{ $tran.Rollback() throw }finally{ $con.Close() $con.Dispose() }
途中で Exception を発生させていますので、トランザクションはロールバックされます。
ただし、このケースの場合、クエリの実行自体は SQL Server で正常に実行することができていますので、ロールバックが行われたとしても、クエリストア上は「Regular」として情報の集計が行われることになります。
アプリケーションからのクエリ実行に失敗した場合は、クエリストアから情報の解析を行うことが多いかと思います。
しかし、クエリの実行状態によっては、クエリストアではエラーではなく、通常の実行として、集計が行われているケースもありますので、発生した例外に対して、その例外が発生したクエリは、クエリストア上では、どのような実行タイプとして集計が行われているのかは、意識しておいた方がよさそうですね。