# 通知設計書 90-デッドロック分析

## 概要

本ドキュメントは、SQL Server First Responder Kitのsp_BlitzLock.sqlにおける「デッドロック分析」通知の設計を定義する。この通知は、デッドロック情報の分析処理において、各種チェック（Check 1〜16）の実行状況を示す情報メッセージ群である。

### 本通知の処理概要

この通知は、sp_BlitzLockストアドプロシージャがシステムヘルスセッションや拡張イベントからデッドロック情報を収集・分析する際に、各チェック処理の開始を示す一連の情報メッセージである。Check 1からCheck 16まで、それぞれ異なる観点でデッドロックを分析する。

**業務上の目的・背景**：デッドロックはSQL Serverにおける深刻な問題であり、アプリケーションの可用性とパフォーマンスに直接影響する。sp_BlitzLockは、デッドロックの発生パターン、影響を受けるオブジェクト、関連するクエリなどを包括的に分析し、根本原因の特定と対策立案を支援する。各チェックは異なる観点（データベース別、オブジェクト別、SELECT関連、パラレルデッドロック等）でデッドロックを分析する。

**通知の送信タイミング**：sp_BlitzLockプロシージャの実行中、XMLデータのパース完了後、各チェック処理の開始時に送信される。Check 1から順番に実行され、各チェックの開始時と終了時にメッセージが出力される。

**通知の受信者**：この通知はRAISERROR関数によりSQL Server Management Studio（SSMS）のメッセージウィンドウ、またはsqlcmdなどのコマンドラインツールの標準出力に表示される。主な受信者は、sp_BlitzLockを実行しているDBA、データベース開発者、システム管理者である。

**通知内容の概要**：「Check N {チェック内容} {日時}」形式のメッセージが表示され、各デッドロック分析チェックの実行状況を示す。例えば「Check 1 database deadlocks」「Check 2 select deadlocks」など。

**期待されるアクション**：通知の受信者は、各チェック処理が正常に進行していることを確認し、処理完了を待つ。長時間停止している場合は、デッドロックデータ量が多い可能性があるため、@StartDateと@EndDateで期間を絞り込む。

## 通知種別

コンソール出力（RAISERROR WITH NOWAIT）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（WITH NOWAITオプションにより即座に出力） |
| 優先度 | 低（情報レベル、重大度0） |
| リトライ | なし（単発の情報メッセージ） |

### 送信先決定ロジック

sp_BlitzLockを実行しているセッションのクライアント接続に対して直接出力される。送信先の動的な決定ロジックは存在せず、実行元のセッションに対して常に通知される。

## 通知テンプレート

### メール通知の場合

該当なし（コンソール出力のみ）

### 本文テンプレート

各チェックで異なるメッセージが出力される：

```
Check 1  database deadlocks {日時}
Check 2 select deadlocks {日時}
Check 3 object deadlocks {日時}
Check 3 (continued) index deadlocks {日時}
...
Check 10 more info, BlitzIndex {日時}
Check 11 deadlock wait time per object {日時}
Check 12 deadlock wait time per database {日時}
Check 13 deadlock count for SQL Agent {日時}
Check 14 parallel deadlocks {日時}
Check 15 sleeping and background deadlocks {日時}
Check 16 implicit transaction deadlocks {日時}
Finished at {日時}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @d | 現在日時 | CONVERT(varchar(40), GETDATE(), 109) | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロシージャ実行 | sp_BlitzLock内の各チェック処理開始 | 常に送信 | 各チェック処理開始時に通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | これらのメッセージは常に出力される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[XMLパース完了] --> B[Check 1 開始]
    B --> C[RAISERROR Check 1]
    C --> D[データベース別デッドロック集計]
    D --> E[RAISERROR Finished]
    E --> F[Check 2 開始]
    F --> G[RAISERROR Check 2]
    G --> H[SELECT関連デッドロック分析]
    H --> I[RAISERROR Finished]
    I --> J[Check 3〜16 繰り返し]
    J --> K[全チェック完了]
    K --> L[結果出力]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| #deadlock_process | デッドロックプロセス情報 | ローカル一時テーブル |
| #deadlock_owner_waiter | 所有者/待機者情報 | ローカル一時テーブル |
| sys.databases | RCSI設定確認 | Check 2で使用 |

### テーブル別参照項目詳細

#### #deadlock_process

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| database_name | データベース別集計 | GROUP BY |
| event_date | デッドロック発生日時 | フィルタリング |
| client_app | アプリケーション名 | フィルタリング |
| host_name | ホスト名 | フィルタリング |
| login_name | ログイン名 | フィルタリング |

#### #deadlock_owner_waiter

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| database_name | データベース別集計 | GROUP BY |
| object_name | オブジェクト別集計 | GROUP BY |
| lock_mode | ロックモード分析 | S, IS等のフィルタ |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| #deadlock_findings | INSERT | 各チェックの分析結果を格納 |

#### #deadlock_findings

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | check_id | 1〜16 | チェック番号 |
| INSERT | database_name | 分析対象DB名 | - |
| INSERT | object_name | 分析対象オブジェクト名 | - |
| INSERT | finding_group | 結果カテゴリ | 例:「Total Database Deadlocks」 |
| INSERT | finding | 分析結果文 | 例:「This database had N deadlocks.」 |
| INSERT | sort_order | ソート順 | ROW_NUMBER()で算出 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| XMLパースエラー | 不正なデッドロックXML | エラーハンドリング済み |
| タイムアウト | 大量のデッドロックデータ | @StartDate/@EndDateで期間を絞る |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（sp_BlitzLock実行時に即座に出力）

## セキュリティ考慮事項

- 通知内容に機密情報は含まれない
- VIEW SERVER STATE権限が必要（sp_BlitzLock実行の前提条件）
- デッドロック情報にはクエリテキストやオブジェクト名が含まれる場合がある

## 備考

- この通知はsp_BlitzLockの進捗表示の一部であり、長時間実行時のユーザーへのフィードバックとして機能する
- WITH NOWAITオプションにより、バッファリングなしで即座にクライアントに送信される
- 重大度0は情報メッセージを意味し、エラーではない
- 各チェックの開始時と終了時（Finished at）の両方でメッセージが出力される
- チェック番号と内容の対応:
  - Check 1: データベース別デッドロック数
  - Check 2: SELECT関連デッドロック（RCSI推奨判定）
  - Check 3: オブジェクト/インデックス別デッドロック
  - Check 10: sp_BlitzIndex用追加情報
  - Check 11: オブジェクト別待機時間
  - Check 12: データベース別待機時間
  - Check 13: SQL Agentジョブ関連デッドロック
  - Check 14: パラレルデッドロック
  - Check 15: スリープ/バックグラウンドセッション関連デッドロック
  - Check 16: 暗黙的トランザクション関連デッドロック

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、デッドロック分析で使用される一時テーブルの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_BlitzLock.sql | `sp_BlitzLock.sql` | #deadlock_process、#deadlock_owner_waiter、#deadlock_findingsテーブルの定義を確認 |

**読解のコツ**: #deadlock_processにはパースされたデッドロック参加者情報が、#deadlock_owner_waiterにはロック所有者/待機者関係が、#deadlock_findingsには分析結果が格納される。

#### Step 2: エントリーポイントを理解する

処理の起点となるXMLパース後のチェック処理開始を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_BlitzLock.sql | `sp_BlitzLock.sql` | 「Begin checks based on parsed values」コメントの位置を確認 |

**主要処理フロー**:
1. **行2265**: /\*Begin checks based on parsed values\*/ コメント
2. **行2275**: /\*Check 1 is deadlocks by database\*/
3. **行2277**: RAISERROR('Check 1 database deadlocks %s', 0, 1, @d) WITH NOWAIT

#### Step 3: 各チェック処理を理解する

各チェックの分析ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_BlitzLock.sql | `sp_BlitzLock.sql` | 各Check Nの処理内容とINSERT文の構造 |

**主要処理フロー**:
- **行2277**: Check 1 - データベース別デッドロック数
- **行2320**: Check 2 - SELECT関連デッドロック（S/ISロックモード判定）
- **行2392**: Check 3 - オブジェクト別デッドロック
- **行2961**: Check 10 - sp_BlitzIndex用情報
- **行3012**: Check 11 - オブジェクト別待機時間
- **行3189**: Check 12 - データベース別待機時間
- **行3355**: Check 13 - SQL Agentジョブ関連
- **行3395**: Check 14 - パラレルデッドロック
- **行3427**: Check 15 - スリープ/バックグラウンド
- **行3487**: Check 16 - 暗黙的トランザクション

### プログラム呼び出し階層図

```
sp_BlitzLock
    |
    +-- [前処理] XMLパース、一時テーブル作成
    |
    +-- /*Begin checks based on parsed values*/
            |
            +-- Check 1: database deadlocks
            |       |
            |       +-- SET @d = GETDATE()
            |       |
            |       +-- RAISERROR('Check 1  database deadlocks %s')  <-- 本通知
            |       |
            |       +-- INSERT #deadlock_findings (データベース別集計)
            |       |
            |       +-- RAISERROR('Finished at %s')
            |
            +-- Check 2: select deadlocks
            |       |
            |       +-- RAISERROR('Check 2 select deadlocks %s')
            |       |
            |       +-- INSERT #deadlock_findings (SELECT関連分析)
            |       |
            |       +-- RAISERROR('Finished at %s')
            |
            +-- Check 3〜16: 各種分析
            |       |
            |       +-- [同様のパターン]
            |
            +-- [結果出力処理]
```

### データフロー図

```
[入力]                          [処理]                              [出力]

#deadlock_process          --> Check 1: GROUP BY database_name  --> #deadlock_findings
- database_name                COUNT_BIG(DISTINCT event_date)       - check_id = 1
- event_date                                                        - finding = 'This database had N deadlocks'
- client_app
- host_name
- login_name

#deadlock_owner_waiter     --> Check 2: lock_mode IN (S, IS)    --> #deadlock_findings
- lock_mode                    sys.databases.is_read_committed_     - check_id = 2
- owner_mode                   snapshot_on                          - finding = 'N deadlocks between read/write'
- waiter_mode

                           --> Check 3〜16: 各種分析             --> #deadlock_findings
                                                                    - check_id = 3〜16

                           コンソール出力 <-- RAISERROR
                           "Check N {内容} {日時}"
                           "Finished at {日時}"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_BlitzLock.sql | `sp_BlitzLock.sql` | ソース | デッドロック分析処理を含むメインストアドプロシージャ |
