# 機能設計書 412-Get-DbaSpinLockStatistic

## 概要

本ドキュメントは、SQL Serverの内部同期メカニズムであるスピンロックの競合統計を取得する`Get-DbaSpinLockStatistic`機能の設計を定義する。

### 本機能の処理概要

本機能は、SQL Serverのsys.dm_os_spinlock_stats DMVからスピンロック使用状況と競合の詳細統計を取得する。スピンロックはSQL Serverが内部的に使用する軽量な同期プリミティブであり、重要なコードセクションやメモリ構造を保護する際の非常に短い待機に使用される。

**業務上の目的・背景**：スピンロック競合はスループットの低下を伴う高CPU使用率として現れる深刻なパフォーマンス問題を引き起こす可能性がある。一般的なシナリオにはtempdb割り当てボトルネック、特定のデータベースオブジェクトへの過度な同時アクセス、SQL Server内部データ構造の問題などがある。Paul Randal氏の高度なパフォーマンストラブルシューティング手法に基づき、待機統計がSOS_SCHEDULER_YIELDや他のCPU関連待機を示す場合にこのデータが不可欠となる。

**機能の利用シーン**：
- CPU使用率が高いがスループットが低い場合の原因調査
- tempdb競合問題の診断
- ラッチ待機やスピンロック圧力の分析
- パフォーマンスベースライン取得

**主要な処理内容**：
1. 指定されたSQL Serverインスタンスへの接続確立（最小バージョン2008）
2. sys.dm_os_spinlock_statsからスピンロック統計を取得
3. 各スピンロックタイプごとの詳細統計を構造化オブジェクトとして出力

**関連システム・外部連携**：SQL Server DMV (sys.dm_os_spinlock_stats)

**権限による制御**：VIEW SERVER STATE権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コマンドライン | 主画面 | PowerShellコンソールからの実行 |

## 機能種別

データ取得・診断処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstance[] | Yes | 対象SQL Serverインスタンス（2008以降） | パイプライン入力可能 |
| SqlCredential | PSCredential | No | 代替認証資格情報 | Windows/SQL認証対応 |
| EnableException | switch | No | 例外の詳細表示有効化 | - |

### 入力データソース

SQL Server DMV: sys.dm_os_spinlock_stats

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverホストのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名 |
| SpinLockName | string | スピンロックタイプ名（例: LOCK_HASH, LOGCACHE_ACCESS） |
| Collisions | bigint | スレッドがスピンロック待機を要した回数 |
| Spins | bigint | ロック取得前の総スピンサイクル数 |
| SpinsPerCollision | decimal | 競合あたりの平均スピン数（効率指標） |
| SleepTime | int | スピン回数超過後のスリープ時間（ミリ秒） |
| Backoffs | bigint | リトライ前にスレッドがバックオフした回数 |

### 出力先

PowerShellパイプライン(PSCustomObject)

## 処理フロー

### 処理シーケンス

```
1. BEGINブロック: SQLクエリ定義
   └─ sys.dm_os_spinlock_statsから全カラムを取得するSQLを構築
   └─ Write-Messageでデバッグ出力

2. processブロック: インスタンスごとの処理ループ
   └─ 2.1 Test-FunctionInterruptで中断チェック
   └─ 2.2 Connect-DbaInstance（MinimumVersion 10）で接続
   └─ 2.3 $server.Query()でSQLクエリ実行
   └─ 2.4 各行をPSCustomObjectに変換して出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[SQLクエリ文字列定義]
    B --> C[Write-Message Debug]
    C --> D{Test-FunctionInterrupt}
    D -->|中断| E[return]
    D -->|継続| F{各SqlInstanceをループ}
    F --> G[Connect-DbaInstance MinVer=10]
    G --> H{接続成功?}
    H -->|No| I[Stop-Function/Continue]
    I --> F
    H -->|Yes| J[クエリ実行]
    J --> K{各行をループ}
    K --> L[PSCustomObject作成]
    L --> M[パイプライン出力]
    M --> K
    K -->|完了| F
    F -->|完了| N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 最小バージョン | SQL Server 2008（バージョン10）以上が必要 | Connect-DbaInstance時 |
| BR-002 | 全スピンロック取得 | フィルタなしで全スピンロックタイプを取得 | 常時 |

### 計算ロジック

SpinsPerCollisionはDMVから直接取得（spins_per_collision列）

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| スピンロック統計取得 | sys.dm_os_spinlock_stats | SELECT | DMVからスピンロック統計を取得 |

### テーブル別操作詳細

#### sys.dm_os_spinlock_stats (DMV)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name | - | スピンロック名 |
| SELECT | collisions | - | 競合回数 |
| SELECT | spins | - | スピン回数 |
| SELECT | spins_per_collision | - | 競合あたりのスピン数 |
| SELECT | sleep_time | - | スリープ時間 |
| SELECT | backoffs | - | バックオフ回数 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | Connect-DbaInstance失敗 | Stop-FunctionでContinue |
| VersionError | バージョンエラー | SQL Server 2008未満 | MinimumVersionで接続拒否 |

### リトライ仕様

リトライ処理なし（単一試行）

## トランザクション仕様

読み取り専用クエリのためトランザクション管理不要

## パフォーマンス要件

- DMVクエリのため通常は高速（数秒以内）
- スピンロックタイプ数に応じた結果行数

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

- VIEW SERVER STATE権限が必要
- SQL認証/Windows認証/Azure AD認証に対応
- 資格情報はPSCredentialで安全に渡される

## 備考

- Paul Randal氏の参照記事: https://www.sqlskills.com/blogs/paul/advanced-performance-troubleshooting-waits-latches-spinlocks/
- Patrick Flynn氏(@sqllensman)による開発

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaSpinLockStatistic.ps1 | `public/Get-DbaSpinLockStatistic.ps1` | 出力PSCustomObjectの構造（118-128行目） |

**読解のコツ**: 各プロパティはsys.dm_os_spinlock_statsの列に直接対応している

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaSpinLockStatistic.ps1 | `public/Get-DbaSpinLockStatistic.ps1` | 関数全体の構造とパラメータ定義 |

**主要処理フロー**:
1. **86-91行目**: パラメータ定義（SqlInstance, SqlCredential, EnableException）
2. **94-106行目**: BEGINブロックでSQLクエリ定義
3. **108-130行目**: processブロックでメイン処理

#### Step 3: クエリ実行とデータ変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaSpinLockStatistic.ps1 | `public/Get-DbaSpinLockStatistic.ps1` | foreach ($row in $server.Query($sql))の処理（117-129行目） |

**主要処理フロー**:
- **112行目**: Connect-DbaInstance -MinimumVersion 10で2008以降に限定
- **117行目**: $server.Query($sql)でクエリ実行
- **118-128行目**: PSCustomObjectへの変換

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

```
Get-DbaSpinLockStatistic
    │
    ├─ Test-FunctionInterrupt
    │      └─ 中断フラグチェック
    │
    ├─ Connect-DbaInstance (MinimumVersion 10)
    │      └─ SMO接続の確立
    │
    └─ $server.Query()
           └─ sys.dm_os_spinlock_statsへのクエリ実行
```

### データフロー図

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

SqlInstance ──────▶ Connect-DbaInstance ──────┐
                   (MinimumVersion=10)        │
                                              │
SqlCredential ────▶ 認証処理 ────────────────┘
                          │
                          ▼
                   $server.Query($sql)
                          │
                          ▼
              sys.dm_os_spinlock_stats
                          │
                          ▼
               foreach ($row in results)
                          │
                          ▼
                   PSCustomObject ──────▶ パイプライン出力
                   (各スピンロック行)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaSpinLockStatistic.ps1 | `public/Get-DbaSpinLockStatistic.ps1` | ソース | メイン関数実装 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続処理 |
