-
Notifications
You must be signed in to change notification settings - Fork 0
MS_CausalAnalysisExamples
- 戻る(障害発生時の分析)
- 因果関係の分析例
以下は障害発生までに至る因果関係の事例になります。
- 「現象」と「原因」はプラットフォームの内部状態を理解しなければ紐付けできません。
- 逆に言えばプラットフォームの内部動作を理解しておけば、この紐付けも容易になります。
これを行うには
- プラットフォームに対する知識
- 状態確認・分析方法に関する知識
- 分析結果から原因を推測するスキル
が必要になります。
補足(本ページの読み方): 各事例が
**「現象 → 分析手順 → 原因 → 解決策」**という同じ型で書かれている点が要点である。
障害対応では「現象」から直接「解決策」に飛びたくなるが、
間の 2 段を飛ばすと再発する(対症療法で終わる)。また、分析手順が
「ログ → カウンタ → ダンプ → プロファイル」の順、
すなわち軽い手段から重い手段へ並んでいることにも注目したい。
段階 手段 本番への影響 1 ログ(ログの収集、イベント ログ) ほぼ無し 2 パフォーマンス カウンタ 小さい 3 ダンプ取得(ダンプの概要) プロセスが一時停止する 4 プロファイラ 大きい。通常は開発環境で
- 例外でクラッシュ
- xxx例外
- ログ確認
WER(Windows Error Report)などから例外情報を確認する。 - ダンプ+ダンプ解析
- 本番環境でのみ再現する場合はクラッシュダンプ取得+解析
- 例外情報と、例外を発生させているスレッドのスタックを確認する。
- プログラムのプロファイル
開発環境で再現できる場合、プログラムをデバッグ
プログラムのバグによる未処理例外
- 問題の PG を修正
- ミドルウェアへのパッチ適用等
補足: クラッシュ ダンプの取得は
クラッシュ ダンプ、
ダンプ取得に使用するツールの一覧を参照。
.NET では未処理例外がプロセスを終了させる(.NET 2.0 以降)ため、
AppDomain.UnhandledExceptionでログだけ残して落ちる、という設計になる。
- 性能が出ない → 例外でクラッシュ
- メモリ使用量大 → GC、ページング → オーバヘッド大 → OutOfMemory 例外
- ログ確認
WER(Windows Error Report)などから例外情報を確認する。 - パフォーマンスカウンタ
ページング、メモリリークの確認、プロセスの特定など - ダンプ+ダンプ解析
- 本番環境でのみ再現する場合はダンプ取得+解析
- 仮想アドレス空間の確保状況を確認する。
- プログラムのプロファイル
- 開発環境で再現できる場合、プロファイルを実行
- ヒープの使用状況を確認する。
プログラムのバグによるメモリリーク
- 問題の PG を修正
- ミドルウェアへのパッチ適用等
補足(この因果の連鎖が重要): 現象の 2 行目が
**「メモリ使用量大 → GC → オーバヘッド大 → OutOfMemory」**と
段階を追って書かれている点に価値がある。実際には、OutOfMemory で落ちる前に「遅くなる」段階がある。
- メモリ使用量が増える
- GC の頻度と時間が増える(特に Gen2 / Full GC)
- ページングが発生し、ディスク I/O が増える
- 最終的に確保に失敗して
OutOfMemoryExceptionつまり、「性能劣化」の段階で捕まえられれば
クラッシュ前に手が打てるということである。
監視すべきカウンタは以下。
カウンタ 見るもの .NET CLR Memory\% Time in GCGC に費やしている時間の割合(10% 超で要注意) .NET CLR Memory\# Gen 2 CollectionsFull GC の頻度 Process\Private Bytesプロセスの実使用量(右肩上がりならリーク) Memory\Pages/secページング 詳細はメモリ リーク、
.NET のメモリ リーク、
物理メモリの管理を参照。
なお、32bit プロセスでは物理メモリに余裕があっても
アドレス空間(2GB)が先に尽きる(WOW64)。
- 性能が出ない
- CPU 使用率大
- パフォーマンスカウンタ
CPU リソースを消費しているプロセスの特定など - ダンプ+ダンプ解析
本番環境でのみ再現する場合はハングダンプ取得+解析
(ハングダンプを取得可能なほど CPU を消費する場合に限り)
ハングしていると思われるスレッドのスタックを確認する。 - プログラムのプロファイル
開発環境で再現できる場合、プロファイラを実行して問題個所を特定
プログラムのバグ・問題による CPU リソース大量消費
(種々の効率の悪い処理に起因する)
- 問題の PG を修正
- ミドルウェアへのパッチ適用等
補足(CPU 使用率大の典型パターン): 「効率の悪い処理」の中身は
概ね以下のいずれかに分類できる。
パターン 例 GC の暴走 前項の OutOfMemory の手前の状態。CPU 使用率として現れる 無限ループ / スピン待ち ロック待ちを whileで回している正規表現のバックトラック爆発 ReDoS。入力次第で指数的に遅くなる 例外の多発 例外はスタック巻き戻しのコストが高い。制御フローに使わない 文字列連結 ループ内の +=。StringBuilderを使う過剰なシリアライズ 大きなオブジェクトの反復変換 CPU 使用率が高いのが自プロセスか、GC か、他プロセスかを
最初に切り分けることが重要である
(OSのフリーズ、初回が遅い!も参照)。
- 性能が出ない
- ディスク IO ネック
- パフォーマンスカウンタ
ディスク・リソースを消費しているプロセスの特定など - プログラムのプロファイル
開発環境で再現できる場合、プロファイラを実行して問題個所を特定
プログラムの問題によるディスク・リソース大量消費
- 問題の PG を修正
- ミドルウェアへのパッチ適用等
補足: ディスク I/O では、IOPS・スループット・レイテンシの
どれが飽和しているかで対処が変わる。
カウンタ 見るもの PhysicalDisk\Avg. Disk sec/Read (Write)レイテンシ。HDD で 20ms 超、SSD で 5ms 超なら遅い PhysicalDisk\Disk Transfers/secIOPS PhysicalDisk\Disk Bytes/secスループット PhysicalDisk\Current Disk Queue Length待ち行列 なお、ページングによるディスク I/O(前述の OutOfMemory の連鎖)と
アプリのファイル I/O は分けて考える必要がある。
DB サーバの場合は
SQL Server のファイルの配置、
RAIDも参照。
- 性能が出ない
- SQL の完了が遅い
- パフォーマンスカウンタ
- ハードウェア・リソース消費の確認
- SQL Server の状態の確認
- SQL ログ
SQL Server のイベントの確認(SQL Server のログ) - SQL トレース
DBMS インスタンスの処理しているクエリの確認
(SQLプロファイラ(SQLトレース)) - 実行プランの確認
問題の SQL の実行プランに問題が無いか確認
(実行プランのグラフィカル表示)
プログラムの問題によるディスク・リソース大量消費
- DB サーバのリソース不足
- ハードウェア・リソースの追加
- DB 設定の問題によるリソース大量消費
- バッファ・キャッシュの拡張(SQL Server の基本的な設定)
- DB 拡張、ログ記録、制約、トリガ等の一時的無効化
(SQL Server 大量データ処理時の性能問題)
- DML の問題によるリソース大量消費
- 非効率なデータアクセスを修正する。
- リソースを大量消費しないように修正する。
- インデックスを使用するように記述(ルールベース)
- インデックスを使用するように統計情報を更新(コストベース)
(SQL Server のオプティマイザ)
- DDL の問題によるリソース大量消費
- インデックスを張る(SQL Server のインデックス)。
- 非正規化を実施。
移行メモ(正誤): この事例の「原因」欄が
直前の「ディスク 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_YIELDCPU また、SQL Server 2016 以降は
クエリ ストアが実行プランと実行統計を自動で蓄積するため、
「いつから遅くなったか」を後追いで特定できる
(SQL Server のログ)。
全体の分析手順はSQL Server 問題の分析方法を参照。
Tags: 移行, 障害対応, デバッグ
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。