Skip to content

MS_CausalAnalysisExamples

nishi_74322014 edited this page Aug 18, 2026 · 1 revision

因果関係の分析例

概要

以下は障害発生までに至る因果関係の事例になります。

  • 「現象」と「原因」はプラットフォームの内部状態を理解しなければ紐付けできません。
  • 逆に言えばプラットフォームの内部動作を理解しておけば、この紐付けも容易になります。

これを行うには

  1. プラットフォームに対する知識
  2. 状態確認・分析方法に関する知識
  3. 分析結果から原因を推測するスキル

が必要になります。

補足(本ページの読み方): 各事例が
**「現象 → 分析手順 → 原因 → 解決策」**という同じ型で書かれている点が要点である。
障害対応では「現象」から直接「解決策」に飛びたくなるが、
間の 2 段を飛ばすと再発する(対症療法で終わる)。

また、分析手順が
「ログ → カウンタ → ダンプ → プロファイル」の順、
すなわち軽い手段から重い手段へ
並んでいることにも注目したい。

段階 手段 本番への影響
1 ログ(ログの収集イベント ログ ほぼ無し
2 パフォーマンス カウンタ 小さい
3 ダンプ取得(ダンプの概要 プロセスが一時停止する
4 プロファイラ 大きい。通常は開発環境で

詳細

xxx例外の発生

現象

  1. 例外でクラッシュ
  2. xxx例外

分析手順

  1. ログ確認
    WER(Windows Error Report)などから例外情報を確認する。
  2. ダンプ+ダンプ解析
    • 本番環境でのみ再現する場合はクラッシュダンプ取得+解析
    • 例外情報と、例外を発生させているスレッドのスタックを確認する。
  3. プログラムのプロファイル
    開発環境で再現できる場合、プログラムをデバッグ

原因

プログラムのバグによる未処理例外

解決策

  • 問題の PG を修正
  • ミドルウェアへのパッチ適用等

補足: クラッシュ ダンプの取得は
クラッシュ ダンプ
ダンプ取得に使用するツールの一覧を参照。
.NET では未処理例外がプロセスを終了させる(.NET 2.0 以降)ため、
AppDomain.UnhandledException でログだけ残して落ちる、という設計になる。

OutOfMemory例外の発生

現象

  1. 性能が出ない → 例外でクラッシュ
  2. メモリ使用量大 → GC、ページング → オーバヘッド大 → OutOfMemory 例外

分析手順

  1. ログ確認
    WER(Windows Error Report)などから例外情報を確認する。
  2. パフォーマンスカウンタ
    ページング、メモリリークの確認、プロセスの特定など
  3. ダンプ+ダンプ解析
    • 本番環境でのみ再現する場合はダンプ取得+解析
    • 仮想アドレス空間の確保状況を確認する。
  4. プログラムのプロファイル
    • 開発環境で再現できる場合、プロファイルを実行
    • ヒープの使用状況を確認する。

原因

プログラムのバグによるメモリリーク

解決策

  • 問題の PG を修正
  • ミドルウェアへのパッチ適用等

補足(この因果の連鎖が重要): 現象の 2 行目が
**「メモリ使用量大 → GC → オーバヘッド大 → OutOfMemory」**と
段階を追って書かれている点に価値がある。

実際には、OutOfMemory で落ちる前に「遅くなる」段階がある

  1. メモリ使用量が増える
  2. GC の頻度と時間が増える(特に Gen2 / Full GC)
  3. ページングが発生し、ディスク I/O が増える
  4. 最終的に確保に失敗して OutOfMemoryException

つまり、「性能劣化」の段階で捕まえられれば
クラッシュ前に手が打てる
ということである。
監視すべきカウンタは以下。

カウンタ 見るもの
.NET CLR Memory\% Time in GC GC に費やしている時間の割合(10% 超で要注意)
.NET CLR Memory\# Gen 2 Collections Full GC の頻度
Process\Private Bytes プロセスの実使用量(右肩上がりならリーク)
Memory\Pages/sec ページング

詳細はメモリ リーク
.NET のメモリ リーク
物理メモリの管理を参照。
なお、32bit プロセスでは物理メモリに余裕があっても
アドレス空間(2GB)が先に尽きるWOW64)。

CPU使用率大

現象

  1. 性能が出ない
  2. CPU 使用率大

分析手順

  1. パフォーマンスカウンタ
    CPU リソースを消費しているプロセスの特定など
  2. ダンプ+ダンプ解析
    本番環境でのみ再現する場合はハングダンプ取得+解析
    (ハングダンプを取得可能なほど CPU を消費する場合に限り)
    ハングしていると思われるスレッドのスタックを確認する。
  3. プログラムのプロファイル
    開発環境で再現できる場合、プロファイラを実行して問題個所を特定

原因

プログラムのバグ・問題による CPU リソース大量消費
(種々の効率の悪い処理に起因する)

解決策

  • 問題の PG を修正
  • ミドルウェアへのパッチ適用等

補足(CPU 使用率大の典型パターン): 「効率の悪い処理」の中身は
概ね以下のいずれかに分類できる。

パターン
GC の暴走 前項の OutOfMemory の手前の状態。CPU 使用率として現れる
無限ループ / スピン待ち ロック待ちを while で回している
正規表現のバックトラック爆発 ReDoS。入力次第で指数的に遅くなる
例外の多発 例外はスタック巻き戻しのコストが高い。制御フローに使わない
文字列連結 ループ内の +=StringBuilder を使う
過剰なシリアライズ 大きなオブジェクトの反復変換

CPU 使用率が高いのが自プロセスか、GC か、他プロセスか
最初に切り分けることが重要である
OSのフリーズ初回が遅い!も参照)。

ディスクIOネック

現象

  1. 性能が出ない
  2. ディスク IO ネック

分析手順

  1. パフォーマンスカウンタ
    ディスク・リソースを消費しているプロセスの特定など
  2. プログラムのプロファイル
    開発環境で再現できる場合、プロファイラを実行して問題個所を特定

原因

プログラムの問題によるディスク・リソース大量消費

解決策

  • 問題の PG を修正
  • ミドルウェアへのパッチ適用等

補足: ディスク I/O では、IOPS・スループット・レイテンシ
どれが飽和しているかで対処が変わる。

カウンタ 見るもの
PhysicalDisk\Avg. Disk sec/Read (Write) レイテンシ。HDD で 20ms 超、SSD で 5ms 超なら遅い
PhysicalDisk\Disk Transfers/sec IOPS
PhysicalDisk\Disk Bytes/sec スループット
PhysicalDisk\Current Disk Queue Length 待ち行列

なお、ページングによるディスク I/O(前述の OutOfMemory の連鎖)と
アプリのファイル I/O は分けて考える必要がある。
DB サーバの場合は
SQL Server のファイルの配置
RAIDも参照。

SQLの完了が遅い

現象

  1. 性能が出ない
  2. SQL の完了が遅い

分析手順

  1. パフォーマンスカウンタ
    • ハードウェア・リソース消費の確認
    • SQL Server の状態の確認
  2. SQL ログ
    SQL Server のイベントの確認(SQL Server のログ
  3. SQL トレース
    DBMS インスタンスの処理しているクエリの確認
    SQLプロファイラ(SQLトレース)
  4. 実行プランの確認
    問題の SQL の実行プランに問題が無いか確認
    実行プランのグラフィカル表示

原因

プログラムの問題によるディスク・リソース大量消費

解決策

  • DB サーバのリソース不足
    • ハードウェア・リソースの追加
  • DB 設定の問題によるリソース大量消費
  • DML の問題によるリソース大量消費
    • 非効率なデータアクセスを修正する。
    • リソースを大量消費しないように修正する。
    • インデックスを使用するように記述(ルールベース)
    • インデックスを使用するように統計情報を更新(コストベース)
      SQL Server のオプティマイザ
  • DDL の問題によるリソース大量消費

移行メモ(正誤): この事例の「原因」欄が
直前の「ディスク IO ネック」と同じ
**「プログラムの問題によるディスク・リソース大量消費」**になっているが、
続く「解決策」がリソース不足・DB 設定・DML・DDL と
4 系統に分かれていることから、
コピー時の取り違えと思われる。
実際の原因は解決策の 4 分類に対応するものと読むのが妥当である。

補足(現在の起点は「待ち事象」): SQL が遅い場合、
現在はまず何を待っているかから入るのが定石である。

SELECT wait_type, wait_time_ms, waiting_tasks_count, signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (N'SLEEP_TASK', N'BROKER_TASK_STOP', N'XE_TIMER_EVENT')
ORDER BY wait_time_ms DESC;
待ち事象 疑うもの
PAGEIOLATCH_* ディスク I/O(本ページの分類どおり)
LCK_M_* ロック待ちSQL Server でのロック・タイムアウト
WRITELOG ログ書き込み(SQL Server のファイルの配置
CXPACKET / CXCONSUMER 並列クエリ(SQL Server のファイル・グループ
RESOURCE_SEMAPHORE メモリ グラント待ち(SQL Server 結合方式の問題を監視する
SOS_SCHEDULER_YIELD CPU

また、SQL Server 2016 以降は
クエリ ストアが実行プランと実行統計を自動で蓄積するため、
「いつから遅くなったか」を後追いで特定できる
SQL Server のログ)。
全体の分析手順はSQL Server 問題の分析方法を参照。


Tags: 移行, 障害対応, デバッグ

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally