# 通知設計書 101-シングルユーザー設定

## 概要

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

### 本通知の処理概要

この通知は、データベース復元プロセスにおいて、既存のデータベースをシングルユーザーモードに設定する際に出力される情報メッセージである。

**業務上の目的・背景**：データベースの復元処理を実行する際、既存のデータベースに対して他のユーザー接続が存在すると復元処理が失敗する。このため、復元処理開始前にデータベースをシングルユーザーモードに設定し、他の接続を強制的に切断する必要がある。この通知は、DBAがその処理の進行状況を把握し、復元プロセスが正常に進行していることを確認するために重要である。

**通知の送信タイミング**：`@ExistingDBAction = 1` が設定されており、かつ復元対象データベースが既に存在する場合に、RAISERROR関数を通じて即座に出力される。データベースの状態が 'RESTORING' でない場合にのみ、実際のシングルユーザーモード設定が実行される。

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

**通知内容の概要**：「Setting single user」というシンプルなメッセージが出力され、データベースがシングルユーザーモードへ移行中であることを示す。

**期待されるアクション**：通知を受け取った受信者は、復元プロセスが正常に進行していることを確認し、後続の処理（バックアップファイルからの復元など）を待機する。エラーが発生した場合は、データベースの現在の状態を確認し、手動で介入する必要があるかを判断する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

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

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

### 本文テンプレート

```
Setting single user
```

### 添付ファイル

なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロシージャ実行 | sp_DatabaseRestore の @ExistingDBAction パラメータが 1 に設定されている | @RestoreDatabaseID IS NOT NULL（対象DBが存在） | 既存データベースの排他アクセス確保のため |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| @ExistingDBAction が 0 または 2-4 | シングルユーザーモード設定が不要 |
| @RestoreDatabaseID IS NULL | 復元対象データベースが存在しない場合は不要 |
| DATABASEPROPERTYEX が 'RESTORING' | 既に復元中のデータベースには設定不要 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[sp_DatabaseRestore 実行開始] --> B{@ExistingDBAction = 1?}
    B -->|No| Z[他の処理へ]
    B -->|Yes| C{@RestoreDatabaseID IS NOT NULL?}
    C -->|No| D[警告出力: @ExistingDBAction > 0, but no existing @RestoreDatabaseName]
    C -->|Yes| E[RAISERROR 'Setting single user']
    E --> F{データベース状態 = RESTORING?}
    F -->|Yes| G[スキップ: 既に復元中]
    F -->|No| H[ALTER DATABASE SET SINGLE_USER WITH ROLLBACK IMMEDIATE]
    H --> I[CommandExecute 実行]
    I --> J[次の処理へ]
    G --> J
    D --> J
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| sys.databases | データベースの存在確認 | DB_ID 関数経由 |
| sys.sysprocesses | 現在の接続情報（後続処理で使用） | @ExistingDBAction = 2,3 の場合 |

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

#### sys.databases

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| database_id | 対象DBの存在確認 | DB_ID(@RestoreDatabaseName) |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| dbo.CommandLog | INSERT | CommandExecute によるログ記録（@LogToTable = 'Y' の場合） |

#### CommandLog テーブル

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 実行失敗 | ALTER DATABASE の実行権限不足 | sysadmin または db_owner 権限を確認 |
| タイムアウト | ROLLBACK IMMEDIATE が長時間かかる | 長時間トランザクションを手動で終了 |
| 状態取得失敗 | DATABASEPROPERTYEX が NULL を返す | データベースの状態を手動確認 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（プロシージャ実行ごとに1回） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（プロシージャ実行時に即座に出力）

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

- ALTER DATABASE SET SINGLE_USER は sysadmin 権限または対象データベースの db_owner 権限が必要
- ROLLBACK IMMEDIATE により他ユーザーのトランザクションが強制ロールバックされる
- 本操作のログは CommandLog テーブルに記録される

## 備考

- @Debug = 1 の場合、実行される SQL ステートメントも追加で出力される
- @Execute = 'N' の場合、メッセージは出力されるが実際の ALTER DATABASE は実行されない
- 後続処理として接続切断（@ExistingDBAction = 2,3）やデータベース削除（@ExistingDBAction = 3）、オフライン設定（@ExistingDBAction = 4）が続く場合がある

---

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

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

### 推奨読解順序

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

本通知はシンプルな情報メッセージであり、特別なデータ構造は使用していない。主に入力パラメータと局所変数を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | パラメータ定義（14-54行目）で @ExistingDBAction の役割を理解 |

**読解のコツ**: @ExistingDBAction は TINYINT 型で、0-4 の値を取る。1 がシングルユーザーモード設定を意味する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 818-906行目で @ExistingDBAction の処理分岐を確認 |

**主要処理フロー**:
1. **818行目**: `IF @ExistingDBAction BETWEEN 1 AND 4` - ExistingDBAction フラグの評価開始
2. **821行目**: `IF @RestoreDatabaseID IS NOT NULL` - 復元対象DBの存在確認
3. **823-824行目**: `IF @ExistingDBAction = 1` - シングルユーザーモード分岐
4. **825行目**: `RAISERROR('Setting single user', 0, 1) WITH NOWAIT` - 本通知の出力

#### Step 3: ALTER DATABASE ステートメントの生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 826行目で ALTER DATABASE ステートメントの構築 |

**主要処理フロー**:
- **826行目**: `SET @sql = N'ALTER DATABASE ' + @RestoreDatabaseName + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'`

#### Step 4: CommandExecute による実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sp_DatabaseRestore.sql | `sp_DatabaseRestore.sql` | 836行目で CommandExecute の呼び出し |

**主要処理フロー**:
- **834-836行目**: データベース状態確認と CommandExecute 実行

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

```
sp_DatabaseRestore
    │
    ├─ DB_ID(@RestoreDatabaseName)
    │      └─ データベースIDの取得
    │
    ├─ RAISERROR('Setting single user', 0, 1)
    │      └─ 本通知の出力
    │
    ├─ DATABASEPROPERTYEX(@UnquotedRestoreDatabaseName, 'STATUS')
    │      └─ データベース状態の確認
    │
    └─ dbo.CommandExecute
           ├─ @Command = ALTER DATABASE ... SET SINGLE_USER
           ├─ @CommandType = 'ALTER DATABASE SINGLE_USER'
           └─ @LogToTable = 'Y'
```

### データフロー図

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

@ExistingDBAction = 1 ───▶ パラメータ評価 ───────────────▶ (分岐判定)
                               │
@RestoreDatabaseName ────▶ DB_ID 確認 ──────────────────▶ @RestoreDatabaseID
                               │
                               ▼
                         RAISERROR ──────────────────────▶ 'Setting single user'
                               │                           (メッセージ出力)
                               ▼
                    DATABASEPROPERTYEX ─────────────────▶ (状態チェック)
                               │
                               ▼
                      CommandExecute ───────────────────▶ CommandLog テーブル
                               │
                               ▼
                    ALTER DATABASE 実行 ─────────────────▶ データベース状態変更
```

### 関連ファイル一覧

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