# 通知設計書 105-ログ復元

## 概要

本ドキュメントは、SQL Server First Responder Kit の sp_DatabaseRestore プロシージャにおける「ログ復元」情報通知の設計を定義する。

### 本通知の処理概要

この通知は、データベース復元プロセスにおいて、トランザクションログの復元処理が開始される際に出力される情報メッセージである。

**業務上の目的・背景**：データベースの完全復元では、フルバックアップの復元後にトランザクションログの復元が必要となる。特にポイントインタイムリカバリ（特定時点への復旧）を行う場合、複数のログバックアップを順次適用する必要がある。この通知により、DBAはログ復元フェーズに入ったことを把握でき、復元プロセス全体の進行状況を監視できる。

**通知の送信タイミング**：フルバックアップの復元が完了し、ログバックアップの復元処理に入る際（内部変数 @i が 2 に設定された時点）に出力される。@Execute = 'Y' の場合のみメッセージが出力される。

**通知の受信者**：sp_DatabaseRestore プロシージャを実行しているDBA、またはSQL Server Management Studio (SSMS) のクエリウィンドウで結果を監視しているオペレーター。

**通知内容の概要**：「@i set to 2, restoring logs」というメッセージが出力され、ログ復元フェーズが開始されたことを示す。@i は内部ループ制御変数で、2 はログ復元モードを示す。

**期待されるアクション**：通知を受け取った受信者は、ログ復元処理が正常に進行していることを確認する。複数のログバックアップがある場合、各ログファイルの復元が順次実行されるため、完了まで待機する。

## 通知種別

RAISERROR によるメッセージ出力（SQL Server メッセージ / SSMS メッセージタブ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（RAISERROR WITH NOWAIT） |
| 優先度 | 情報（Severity 0） |
| リトライ | なし |

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

本通知はクライアント接続に対して直接送信される。sp_DatabaseRestore を実行しているセッションのクライアントが受信者となる。

## 通知テンプレート

### メッセージ通知の場合

| 項目 | 内容 |
|-----|------|
| メッセージ形式 | プレーンテキスト |
| 重大度 | 0（情報） |
| 状態 | 1 |

### 本文テンプレート

```
@i set to 2, restoring logs
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 本メッセージは固定テキスト | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロシージャ実行 | ログ復元ループ内で @i = 2 かつ @Execute = 'Y' | LSN チェックによりログ復元が必要と判定された場合 | ログバックアップの復元処理開始 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| @BackupPathLog IS NULL | ログバックアップパスが指定されていない |
| @i = 1（ログ復元開始前） | まだログ復元フェーズに入っていない |
| @Execute = 'N' | 実行モードでない（メッセージは出力されない） |
| 復元するログがない | LSN チェックでログ復元が不要と判定された |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[フルバックアップ復元完了] --> B{@BackupPathLog IS NOT NULL?}
    B -->|No| Z[ログ復元スキップ]
    B -->|Yes| C[ログファイル一覧取得]
    C --> D[ログ復元ループ開始]
    D --> E{@i = 1?}
    E -->|Yes| F[LSN チェック]
    F --> G{ログ復元必要?}
    G -->|No| H[Debug: No Log to Restore]
    G -->|Yes| I[@i = 2 に設定]
    I --> J[RAISERROR '@i set to 2, restoring logs']
    J --> K[RESTORE LOG 実行]
    K --> L{次のログあり?}
    L -->|Yes| D
    L -->|No| M[ログ復元完了]
    E -->|No| K
    H --> M
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| #Headers | ログバックアップのヘッダー情報（LSN など） | 一時テーブル |
| #SplitLogBackups | ログバックアップファイル一覧 | 一時テーブル |
| @FileList | バックアップファイル一覧 | テーブル変数 |

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

#### #Headers

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| FirstLSN | ログの開始LSN | WHERE BackupType = 2 |
| LastLSN | ログの終了LSN | WHERE BackupType = 2 |

#### #SplitLogBackups

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| BackupPath | ログバックアップのパス | WHERE DenseRank = @LogRestoreRanking |
| BackupFile | ログバックアップのファイル名 | WHERE DenseRank = @LogRestoreRanking |
| DenseRank | 復元順序 | ORDER BY |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| dbo.CommandLog | INSERT | CommandExecute によるログ記録 |

#### CommandLog テーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | CommandType | 'RESTORE LOG' | 実行コマンドの種別 |
| INSERT | DatabaseName | @UnquotedRestoreDatabaseName | 対象データベース名 |
| INSERT | Command | RESTORE LOG ステートメント | 実行されたコマンド全文 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| LSN 不整合 | ログのLSN がフルバックアップと連続していない | バックアップチェーンを確認 |
| ファイル不存在 | ログバックアップファイルが見つからない | ファイルパスを確認 |
| 権限不足 | RESTORE LOG の実行権限がない | sysadmin 権限を確認 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- RESTORE LOG は sysadmin 権限または対象データベースの db_owner 権限が必要
- バックアップファイルへのアクセス権限が必要
- 復元処理のログは CommandLog テーブルに記録される

## 備考

- @Debug = 1 の場合、生成された RESTORE LOG コマンドが出力される
- @Execute = 'N' の場合、本メッセージは出力されない（RAISERROR の条件による）
- @StopAt パラメータが指定されている場合、指定時点で復元を停止する
- 分割バックアップ（複数ファイル）にも対応している

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 269行目で @i TINYINT = 1 の定義を確認 |
| 1-2 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 270-272行目で LSN 関連変数の定義を確認 |
| 1-3 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 1414行目で #SplitLogBackups の定義を確認 |

**読解のコツ**: @i は内部ループ制御変数で、1 = 初回チェック、2 = ログ復元実行モードを示す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 1174-1499行目でログ復元処理全体を確認 |
| 2-2 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 1460-1462行目で本通知の出力箇所を確認 |

**主要処理フロー**:
1. **1174行目**: `IF @BackupPathLog IS NOT NULL` - ログパスの存在確認
2. **1419行目**: `WHILE 1 = 1` - ログ復元ループ開始
3. **1444-1448行目**: LSN チェックによる @i = 2 への変更
4. **1460行目**: `IF @i = 2` - ログ復元モード判定
5. **1462行目**: `IF @Execute = 'Y' RAISERROR('@i set to 2, restoring logs', 0, 1)` - 本通知の出力

#### Step 3: LSN チェックロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 1439-1448行目で LSN 比較ロジックを確認 |

**主要処理フロー**:
- **1444行目**: `IF (@ContinueLogs = 0 AND @LogFirstLSN <= @FullLastLSN AND @FullLastLSN <= @LogLastLSN...)` - フル復元からの継続判定
- **1447行目**: 差分復元からの継続判定

#### Step 4: RESTORE LOG の生成と実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 1464-1488行目で RESTORE LOG の生成と実行 |

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

```
sp_DatabaseRestore
    │
    ├─ フルバックアップ復元
    │      └─ RESTORE DATABASE
    │
    ├─ ログバックアップ処理開始
    │      ├─ ログファイル一覧取得
    │      └─ #SplitLogBackups へ格納
    │
    ├─ ログ復元ループ（WHILE 1 = 1）
    │      ├─ RESTORE HEADERONLY（LSN 取得）
    │      │
    │      ├─ LSN チェック
    │      │      └─ @i = 2 に設定
    │      │
    │      ├─ RAISERROR('@i set to 2, restoring logs')
    │      │      └─ 本通知の出力
    │      │
    │      └─ dbo.CommandExecute
    │             ├─ @Command = RESTORE LOG
    │             └─ @CommandType = 'RESTORE LOG'
    │
    └─ ログ復元完了
```

### データフロー図

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

@BackupPathLog ───────────▶ ログパス検証 ───────────────▶ @FileList
                               │
                               ▼
                      ファイル一覧取得 ──────────────────▶ #SplitLogBackups
                               │
                               ▼
                    RESTORE HEADERONLY ──────────────────▶ #Headers (LSN)
                               │
                               ▼
                        LSN 比較 ────────────────────────▶ @i = 2
                               │
                               ▼
                         RAISERROR ──────────────────────▶ '@i set to 2, restoring logs'
                               │                           (メッセージ出力)
                               ▼
                      CommandExecute ───────────────────▶ CommandLog テーブル
                               │
                               ▼
                    RESTORE LOG 実行 ───────────────────▶ データベース復元
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | ソース | 本通知を発行するストアドプロシージャ本体 |
| CommandExecute | Ola Hallengren Maintenance Solution | 依存プロシージャ | コマンド実行とログ記録を担当 |
