# 画面設計書 34-スナップショット管理

## 概要

本ドキュメントは、dbatoolsにおけるデータベーススナップショット管理機能の設計仕様を定義する。

### 本画面の処理概要

データベーススナップショット管理機能は、SQL Serverのデータベーススナップショットの取得・作成・削除・リストアを行うPowerShellコマンド群を提供する。スナップショットは特定時点のデータベースの読み取り専用コピーであり、迅速なロールバックやテスト環境の構築に使用される。

**業務上の目的・背景**：データベーススナップショットは、バックアップからリストアせずに迅速にデータベースを特定時点に戻すための軽量な手段である。メンテナンス前のセーフティネット、テストシナリオでのデータ状態保存、レポート用の一貫した読み取り専用ビューの提供など、様々な用途で活用される。本機能は、スナップショットのライフサイクル管理を自動化し、ストレージ使用量の監視とクリーンアップを支援する。

**画面へのアクセス方法**：PowerShellコンソールまたはスクリプトから以下のコマンドを実行してアクセスする。
- `Get-DbaDbSnapshot` - スナップショットの取得
- `New-DbaDbSnapshot` - スナップショットの作成
- `Remove-DbaDbSnapshot` - スナップショットの削除
- `Restore-DbaDbSnapshot` - スナップショットからのリストア

**主要な操作・処理内容**：
1. スナップショット情報の取得：インスタンス上のスナップショット一覧とディスク使用量の取得
2. スナップショットの作成：指定データベースのポイントインタイムスナップショット作成
3. スナップショットの削除：不要になったスナップショットの削除
4. スナップショットからのリストア：データベースをスナップショット時点に戻す

**画面遷移**：本機能はCLIベースのため画面遷移は存在しないが、以下のコマンド間で連携が可能。
- `Get-DbaDbSnapshot` から `Remove-DbaDbSnapshot` または `Restore-DbaDbSnapshot` へパイプライン入力
- `Get-DbaDatabase` から `New-DbaDbSnapshot` へパイプライン入力
- データベースバックアップ/リストア機能との補完的な利用

**権限による表示制御**：スナップショットの操作にはデータベースのCREATE DATABASE権限またはsysadmin固定サーバーロールのメンバーシップが必要。リストアにはデータベースの排他アクセスが必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 279 | Get-DbaDbSnapshot | 主機能 | データベーススナップショットの取得 |
| 280 | New-DbaDbSnapshot | 主機能 | データベーススナップショットの作成 |
| 281 | Remove-DbaDbSnapshot | 主機能 | データベーススナップショットの削除 |
| 47 | Restore-DbaDbSnapshot | 補助機能 | スナップショットからのリストア |

## 画面種別

CLI（コマンドラインインターフェース）- PowerShellコマンド

## URL/ルーティング

N/A（PowerShellモジュールのコマンドとして提供）

## 入出力項目

### Get-DbaDbSnapshot

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | 必須 | 対象SQLインスタンス |
| SqlCredential | PSCredential | - | 代替認証情報 |
| Database | object[] | - | ソースデータベース名フィルター |
| ExcludeDatabase | object[] | - | 除外ソースデータベース名 |
| Snapshot | object[] | - | スナップショット名フィルター |
| ExcludeSnapshot | object[] | - | 除外スナップショット名 |
| EnableException | switch | - | 例外処理の有効化 |

### New-DbaDbSnapshot

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | - | 対象SQLインスタンス |
| SqlCredential | PSCredential | - | 代替認証情報 |
| Database | object[] | - | 対象データベース名 |
| ExcludeDatabase | object[] | - | 除外データベース名 |
| AllDatabases | switch | - | 全データベースを対象 |
| Name | string | - | スナップショット名（単一DB時） |
| NameSuffix | string | - | スナップショット名サフィックス |
| Path | string | - | スナップショットファイルパス |
| Force | switch | - | FILESTREAMありでも部分スナップショットを作成 |
| InputObject | Database[] | - | パイプライン入力用データベースオブジェクト |
| EnableException | switch | - | 例外処理の有効化 |

### Remove-DbaDbSnapshot

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | - | 対象SQLインスタンス |
| SqlCredential | PSCredential | - | 代替認証情報 |
| Database | string[] | - | ソースデータベース名 |
| ExcludeDatabase | string[] | - | 除外ソースデータベース名 |
| Snapshot | string[] | - | 削除対象スナップショット名 |
| InputObject | Database[] | - | パイプライン入力用スナップショットオブジェクト |
| AllSnapshots | switch | - | 全スナップショットを削除 |
| Force | switch | - | アクティブ接続を切断して削除 |
| EnableException | switch | - | 例外処理の有効化 |

### Restore-DbaDbSnapshot

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| SqlInstance | DbaInstance[] | - | 対象SQLインスタンス |
| SqlCredential | PSCredential | - | 代替認証情報 |
| Database | object[] | - | リストア先データベース名 |
| ExcludeDatabase | object[] | - | 除外データベース名 |
| Snapshot | object[] | - | リストア元スナップショット名 |
| InputObject | Database[] | - | パイプライン入力用スナップショットオブジェクト |
| Force | switch | - | 他のスナップショットを削除してリストア |
| EnableException | switch | - | 例外処理の有効化 |

## 表示項目

### Get-DbaDbSnapshot / New-DbaDbSnapshot 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQLサーバーのコンピュータ名 |
| InstanceName | string | SQLインスタンス名 |
| SqlInstance | string | 完全なSQLインスタンス名 |
| Name | string | スナップショット名 |
| SnapshotOf | string | ソースデータベース名（DatabaseSnapshotBaseName） |
| CreateDate | DateTime | スナップショット作成日時 |
| DiskUsage | dbasize | ディスク使用量 |

### Remove-DbaDbSnapshot 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQLサーバーのコンピュータ名 |
| InstanceName | string | SQLインスタンス名 |
| SqlInstance | string | 完全なSQLインスタンス名 |
| Name | string | スナップショット名 |
| Status | string | 操作結果（Dropped/エラーメッセージ） |

### Restore-DbaDbSnapshot 出力

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQLサーバーのコンピュータ名 |
| InstanceName | string | SQLインスタンス名 |
| SqlInstance | string | 完全なSQLインスタンス名 |
| Name | string | データベース名 |
| Status | string | データベース状態 |
| IsAccessible | bool | アクセス可能フラグ |
| RecoveryModel | string | 回復モデル |
| Owner | string | 所有者 |

## イベント仕様

### 1-スナップショット取得

Get-DbaDbSnapshotコマンド実行時：
1. SQL Server 2005以降（バージョン9以上）への接続を確認
2. DatabaseSnapshotBaseNameを持つデータベース（スナップショット）を抽出
3. Database/Snapshot/ExcludeDatabase/ExcludeSnapshotでフィルタリング
4. fn_virtualfilestatsからディスク使用量を取得
5. カスタムプロパティ（ComputerName、InstanceName、DiskUsage等）を追加して出力

### 2-スナップショット作成

New-DbaDbSnapshotコマンド実行時：
1. SQL Server 2005以降への接続を確認
2. パス指定時はアクセス権を確認
3. 対象データベースの検証（システムDB、既存スナップショット、メモリ最適化FG、FILESTREAMを確認）
4. スナップショット名の生成（Name、NameSuffix、またはデフォルトのタイムスタンプ形式）
5. カスタムファイル構造の構築
6. SMOのDatabaseオブジェクトを作成してCreate()メソッドを実行
7. 作成後のスナップショット情報をGet-DbaDbSnapshot経由で返却

### 3-スナップショット削除

Remove-DbaDbSnapshotコマンド実行時：
1. 対象のスナップショットオブジェクトを取得
2. DatabaseSnapshotBaseNameの存在を確認（スナップショットかどうか）
3. ShouldProcess確認（-Confirmまたは-WhatIf対応）
4. -Force指定時はRemove-DbaDatabaseを使用（接続切断付き）
5. 通常はDrop()メソッドを実行
6. 結果ステータスを返却

### 4-スナップショットリストア

Restore-DbaDbSnapshotコマンド実行時：
1. 対象のスナップショットの検証（アクセス可能か、FILESTREAMがないか）
2. 同一ソースDBの他のスナップショットを確認（-Force時は自動削除）
3. ログファイル情報を保存（リストア後の設定復元用）
4. RESTORE DATABASE FROM DATABASE_SNAPSHOTを実行
5. デッドロック発生時はリトライ（最大3回）
6. ログファイルの成長設定を復元
7. リストア後のデータベース情報を返却

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| スナップショット取得 | sys.databases, fn_virtualfilestats | SELECT | スナップショット情報の参照 |
| スナップショット作成 | sys.databases | INSERT | 新規スナップショットDB作成 |
| スナップショット削除 | sys.databases | DELETE | スナップショットの削除 |
| スナップショットリストア | 対象データベース全体 | UPDATE | データベースをスナップショット時点に戻す |

### テーブル別更新項目詳細

#### sys.databases（スナップショット作成時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | スナップショット名 | Name/NameSuffixから生成 |
| INSERT | source_database_id | ソースDBのdatabase_id | DatabaseSnapshotBaseNameから |
| INSERT | is_read_only | 1 | スナップショットは常に読み取り専用 |
| INSERT | state | 0 (ONLINE) | 作成成功時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG001 | 警告 | {database} is a snapshot, skipping | スナップショットをソースに指定した場合 |
| MSG002 | 警告 | {database} snapshots are prohibited | システムDBを指定した場合 |
| MSG003 | 警告 | {database} is not accessible, skipping | アクセス不可なDB |
| MSG004 | 警告 | MEMORY_OPTIMIZED_DATA detected, snapshots are not possible | メモリ最適化FGがある場合 |
| MSG005 | 警告 | Filestream detected, skipping. You need to specify -Force | FILESTREAMがある場合 |
| MSG006 | 警告 | A database named {snapname} already exists, skipping | 同名DB存在時 |
| MSG007 | エラー | You must specify a -AllDatabases or -Database to continue | 必須パラメータ不足時 |
| MSG008 | エラー | You passed the Name parameter that is fixed but selected multiple databases | 複数DB選択時にName指定 |
| MSG009 | エラー | {instance} cannot access the directory {path} | パスアクセス不可時 |
| MSG010 | 成功 | Dropped | スナップショット削除成功時 |
| MSG011 | エラー | {snapshot} on {server} is not a database snapshot | スナップショット以外を指定 |
| MSG012 | 警告 | The restore process for {db} from {snap} needs to drop other snapshots | 他のスナップショットがある場合 |
| MSG013 | エラー | Database {snap} on {server} has FileStream group(s). You cannot restore from snapshots | FILESTREAMからのリストア不可 |
| MSG014 | 情報 | Deadlock detected during restore. Retrying | デッドロック検出時 |
| MSG015 | 情報 | Restored. Remember to take a backup now | リストア成功時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| SQL Server 2005未満 | Stop-Functionでエラー出力して続行 |
| データベースにアクセスできない | 警告メッセージを出力してスキップ |
| システムDBを指定 | 警告メッセージを出力してスキップ |
| メモリ最適化FG存在 | 警告メッセージを出力してスキップ |
| FILESTREAM存在（-Forceなし） | 警告メッセージを出力してスキップ |
| スナップショット作成失敗 | Stop-Functionでエラー出力して続行 |
| スナップショット削除失敗 | エラーメッセージをStatusに設定して出力 |
| リストア時の他スナップショット存在 | -Forceがない場合はエラー、ある場合は自動削除 |
| リストア時のデッドロック | 最大3回リトライ、それでも失敗時はエラー |

## 備考

- スナップショットはSQL Server 2005以降でサポート
- SQL Server 2014より前はEnterprise、Developer、Datacenterエディションのみでサポート
- スナップショットは読み取り専用であり、変更不可
- スナップショットはソースDBとページを共有し、変更時のみ新しいページを使用（Copy-on-Write）
- メモリ最適化ファイルグループを持つDBはスナップショット不可
- FILESTREAMファイルグループは部分スナップショットとして除外される（-Force使用時）
- スナップショットからのリストア時、他のスナップショットは事前に削除が必要

---

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

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

### 推奨読解順序

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

スナップショット管理で扱う主要なデータ構造はSMOのDatabaseオブジェクト（スナップショット）である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaDbSnapshot.ps1 | `public/Get-DbaDbSnapshot.ps1` | 出力オブジェクトの構造（行52-73）を確認 |

**読解のコツ**: DatabaseSnapshotBaseNameプロパティがスナップショットを識別する重要なプロパティ。

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

各コマンドのprocess{}ブロックが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaDbSnapshot.ps1 | `public/Get-DbaDbSnapshot.ps1` | 行102-138のprocessブロック |
| 2-2 | New-DbaDbSnapshot.ps1 | `public/New-DbaDbSnapshot.ps1` | 行153-390のbegin/processブロック |
| 2-3 | Remove-DbaDbSnapshot.ps1 | `public/Remove-DbaDbSnapshot.ps1` | 行131-189のbegin/processブロック |
| 2-4 | Restore-DbaDbSnapshot.ps1 | `public/Restore-DbaDbSnapshot.ps1` | 行130-254のbegin/processブロック |

**主要処理フロー（Get-DbaDbSnapshot）**:
1. **行104-108**: Connect-DbaInstanceでバージョン9以上への接続
2. **行109-124**: DatabaseSnapshotBaseNameでフィルタリング
3. **行127-132**: fn_virtualfilestatsからディスク使用量取得
4. **行128-132**: カスタムプロパティ追加と出力

#### Step 3: スナップショット作成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaDbSnapshot.ps1 | `public/New-DbaDbSnapshot.ps1` | 対象DB検証ロジック（行223-239） |
| 3-2 | New-DbaDbSnapshot.ps1 | `public/New-DbaDbSnapshot.ps1` | ファイル構造構築（行290-322） |
| 3-3 | New-DbaDbSnapshot.ps1 | `public/New-DbaDbSnapshot.ps1` | スナップショット作成（行324-345） |

**主要処理フロー（New-DbaDbSnapshot）**:
- **行254-264**: スナップショット名の生成
- **行273-284**: FILESTREAM/メモリ最適化FGのチェック
- **行290-322**: カスタムファイル構造の構築
- **行342-343**: Database.Create()実行

#### Step 4: リストア処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Restore-DbaDbSnapshot.ps1 | `public/Restore-DbaDbSnapshot.ps1` | 事前チェック（行164-183） |
| 4-2 | Restore-DbaDbSnapshot.ps1 | `public/Restore-DbaDbSnapshot.ps1` | リストア実行とリトライ（行199-227） |

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

```
Get-DbaDbSnapshot
    │
    ├─ Connect-DbaInstance (MinimumVersion 9)
    │
    ├─ Database.Query() (fn_virtualfilestats)
    │
    └─ Select-DefaultView (出力整形)

New-DbaDbSnapshot
    │
    ├─ Connect-DbaInstance (MinimumVersion 9)
    │
    ├─ Test-DbaPath (パス確認)
    │
    ├─ Database.Create() (SMOメソッド)
    │
    └─ Get-DbaDbSnapshot (作成確認)

Remove-DbaDbSnapshot
    │
    ├─ Connect-DbaInstance
    │
    ├─ Get-DbaDbSnapshot
    │
    ├─ Remove-DbaDatabase (-Force時)
    │
    └─ Database.Drop() (通常時)

Restore-DbaDbSnapshot
    │
    ├─ Connect-DbaInstance
    │
    ├─ Get-DbaDbSnapshot
    │
    ├─ Remove-DbaDatabase (他スナップショット削除)
    │
    ├─ Stop-DbaProcess (-Force時)
    │
    ├─ Server.Query() (RESTORE DATABASE FROM SNAPSHOT)
    │
    └─ Get-DbaDatabase (リストア確認)
```

### データフロー図

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

SqlInstance    ───▶  Connect-DbaInstance
                            │
Database       ───▶  フィルタリング           ───▶  スナップショット対象
                            │
AllDatabases   ───▶  全DB取得
                            │
Name/NameSuffix ──▶  スナップショット名生成
                            │
                     Database.Create()        ───▶  Database (スナップショット)
                            │
Path           ───▶  ファイル配置             ───▶  .ssファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaDbSnapshot.ps1 | `public/Get-DbaDbSnapshot.ps1` | ソース | スナップショット取得コマンド |
| New-DbaDbSnapshot.ps1 | `public/New-DbaDbSnapshot.ps1` | ソース | スナップショット作成コマンド |
| Remove-DbaDbSnapshot.ps1 | `public/Remove-DbaDbSnapshot.ps1` | ソース | スナップショット削除コマンド |
| Restore-DbaDbSnapshot.ps1 | `public/Restore-DbaDbSnapshot.ps1` | ソース | スナップショットリストアコマンド |
| Get-DbaDatabase.ps1 | `public/Get-DbaDatabase.ps1` | ソース | データベース取得（依存コマンド） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | インスタンス接続（依存コマンド） |
| Remove-DbaDatabase.ps1 | `public/Remove-DbaDatabase.ps1` | ソース | データベース削除（依存コマンド） |
| Stop-DbaProcess.ps1 | `public/Stop-DbaProcess.ps1` | ソース | プロセス停止（依存コマンド） |
| Test-DbaPath.ps1 | `public/Test-DbaPath.ps1` | ソース | パス検証（依存コマンド） |
