カレンダーで実行するのではなく、シグナルで実行した場合、データベースのメンテナンスが失敗します。分割、古い統計情報、ログの成長、ロックの競合は、書き込みワークロードの機能であり、週次スケジュールではありません。スケジュールされたメンテナンスは、最も必要なテーブルをスキップし、その結果として発生するインシデントは誰も気づく前に発火します。
この記事では、cronジョブを応答システムに置き換えています。4つの観測可能な症状(I/O劣化、クエリプラン回帰、ストレージ圧力、ロック競合)はそれぞれ特定のメンテナンス根本原因に遡り、SQL Server、PostgreSQL、MySQLの修正方法が提供されています。静的破損、予兆信号を生成しない唯一の失敗モードは、独自の検出優先の処理を得ます。閉じるスコアカードは、自己評価を可能にします。
初回応答:エンジン間の待機状態の分類
遅いクエリアラートが発生した場合、エンジンに関わらず最初の診断手順は同じです:クエリが待っているものを確認します。待機状態 はデータベースのインシデント分類の入り口です。問題が I/O 制約、ロック制約、または CPU 制約かどうかを伝え、その分類はどのセクションに修正策が含まれているかを決定します。
SQL Server の待機タイプ
PAGEIOLATCH_SH はクエリがディスクからバッファプールにデータページを読み込むのを待っていることを意味します。これはインデックスのフラグメンテーション、バッファキャッシュの圧力を示しています またはストレージサブシステムの過負荷。LCK_M_S と LCK_M_X は、並行トランザクションやメンテナンスオペレーションによるロック保持から、行レベルまたはテーブルレベルのロック競合を示します。CXPACKET (sys.dm_exec_requests で確認可能)は、並列処理のスキューを示し、通常は古い統計情報やインデックスの欠如が最適化器に高コストな並列プランを選択させる原因となります。
PostgreSQL と MySQL の同等物
PostgreSQL は pg_stat_activity を通じて待機診断を公開します。以下のクエリがあなたの診断のエントリーポイントです:
-- PostgreSQL: active session wait events
SELECT pid, wait_event_type, wait_event, state, query
FROM pg_stat_activity
WHERE wait_event IS NOT NULL
AND state != 'idle'
AND backend_type = 'client backend';
上の図は各値をそのターゲットセクションにマッピングしています。一つ非明らかなケースがあります:NULL wait_event の時state = 'active' はクエリが計算制約(PostgreSQLのCPU圧力の同等物)であることを示し、これは古い統計情報やプランの回帰ではなく、I/Oの問題を指している可能性があります。
MySQLの場合、performance_schema.events_waits_current は図に表示される値のソースです。まず performance_schema = ON を my.cnf で確認してください、因为它はMySQL 5.xのビルドの一部でデフォルトで無効化されており、非ゼロのオーバーヘッドを持ちます;MySQL 8.0以降ではデフォルトで有効化されています。SHOW PROCESSLIST はより速いが粒度が粗い表示を提供します。
ウェイトタイプを特定したら、以下のセクションでは各カテゴリをそのメンテナンス根本原因に追跡し、修正方法を示します。オンプレミスとクラウド管理インスタンスを跨ぐハイブリッドトポロジーの場合、ManageEngine OpManager Nexus は両方のウェイトステートとスロークエリデータを単一のトリエージュビューで表面化します。管理型データベースのためのSaaS配信.
症状:I/O劣化と読み取り増幅
バッファキャッシュヒット率が、健康なOLTPワークロードが維持する95~99%の範囲を下回ると、エンジンがメモリで満たすことができないほどディスクからより多くのページを読み取っていることをエンジンが示すクロスエンジンシグナルです。
SQL Serverの専門家たちは通常、90%を警告として、85%をアクションの閾値として扱います。PostgreSQLとMySQLは、pg_statio_user_tablesおよびinformation_schema.INNODB_BUFFER_POOL_STATS(またはSHOW ENGINE INNODB STATUS)で同等のものを公開しています。最も一般的な原因はインデックスのフラグメンテーションです:ページが分割され、B木の葉が非連続な範囲に散らばり、1つの論理読み取りが複数の物理I/Oに変化します。読み取り増幅は、PAGEIOLATCHがSQL Serverを待っているときに現れます。DataFileRead は PostgreSQL で、innodb_data_file は MySQL を待機しています。
クラウド管理インスタンスでは DMV アクセスが制限されている場合(RDS、Azure SQL Managed Instance)、OpManager Nexus の SaaS 配信はそのエージェントを通じて同じバッファプールの可視性を提供します。
インデックスの肥大を診断する
SQL Server: sys.dm_db_index_physical_stats は、フラグメンテーションデータの権威あるソースです。以下のクエリは、1,000ページを超える5%以上のフラグメンテーションを持つインデックスを返します(ページ数フィルタは重要ですなぜなら、非常に小さなインデックスを再構築しても性能の改善は微々たるものです
SELECT
OBJECT_NAME(ips.object_id) AS tbl_name,
i.name AS idx_name,
ips.index_type_desc,
ips.avg_fragmentation_in_percent,
ips.page_count
FROM sys.dm_db_index_physical_stats(
DB_ID(), NULL, NULL, NULL, 'LIMITED') AS ips
JOIN sys.indexes i
ON ips.object_id = i.object_id
AND ips.index_id = i.index_id
WHERE ips.avg_fragmentation_in_percent > 5
AND ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;
'LIMITED' スキャン モードはインデックス割り当て構造のみを走査するため、本番環境で安全で高速です。'SAMPLED' は、非常に大きなテーブルやパーティション分割インデックスの場合に、中程度の I/O コストでデータ ページの統計サンプルを読み取ります。'DETAILED' は完全な走査を行います;オフライン評価のために予約してください。
PostgreSQL: pg_stat_user_tables ビューは最初のサインを提供します。dead_pct 高書き込みテーブルで10~20%を超えることは、手動VACUUMの一般的なトリガーです(この範囲は実践者ガイドラインと一致し、autovacuumのデフォルトは20%でトリガーされます):
SELECT schemaname, relname,
n_dead_tup,
n_live_tup,
round(n_dead_tup::numeric / NULLIF(n_live_tup + n_dead_tup, 0) * 100, 2) AS dead_pct,
last_vacuum,
last_autovacuum
FROM pg_stat_user_tables
WHERE n_live_tup > 10000
ORDER BY n_dead_tup DESC
LIMIT 20;
インデックスレベルのボリューム(VACUUMが回収できない物理的なB-ツリーのボリューム)の場合、pgstattuple拡張機能は2つの関数を公開します。pgstattuple()はfree_percentは、PostgreSQLにおけるavg_fragmentation_in_percent:
CREATE EXTENSION IF NOT EXISTS pgstattuple;
SELECT * FROM pgstattuple('orders_created_at_idx');
pgstatindex()は、B-tree特有のメトリクスを返します:leaf_fragmentation(リーフページのうち論理的な順序でないページの割合、物理的な散らばりを示唆)、avg_leaf_density(50%未満ならば、インデックスに多くの空ページがあることを示唆)
SELECT * FROM pgstatindex('orders_created_at_idx');
両方の関数は対象の関係性に対して完全なスキャンを実行するため、数百GBのインデックスでは実行時間とI/Oが全オブジェクトの順次読み込みと比較的可能です — その他の重い診断と同様にスケジュールし、熱心なループ内で実行しないでください.
高いfree_percentと低いleaf_fragmentationVACUUMによって完全な再構築ではなく、スペースを回収できることを示唆する場合があります。値はfree_percent20~30%の範囲にあるものはREINDEXのために広く使われるトリガー; 負荷と現在のコミュニティガイドラインを確認して閾値を調整してください。
MySQL:クエリinformation_schema.TABLESInnoDB テーブルスペースのフラグメンテーションについて:
SELECT table_schema, table_name,
round(data_length / 1024 / 1024, 2) AS data_mb,
round(data_free / 1024 / 1024, 2) AS free_mb,
round(data_free / (data_length + index_length + data_free) * 100, 2) AS frag_pct
FROM information_schema.TABLES
WHERE engine = 'InnoDB'
AND data_free > 0
ORDER BY data_free DESC
LIMIT 10;
この指標は、テーブルごとのテーブルスペース(innodb_file_per_table = ON、MySQL 5.6以降のデフォルト)と一緒にのみ意味があります;共有テーブルスペースのデプロイメントでは、data_free はグローバルな ibdata ファイル内の未使用スペースを反映し、InnoDBの各行で完全に同一の形で繰り返されます.
20%を超える frag_pct を持つテーブルは一般的に候補として扱われますOPTIMIZE TABLE または pt-online-schema-change(この閾値は実践者のガイドラインではなく、MySQLの文書化された制限ではありません)。
エンジンによる修復とダウンタイム耐性
Microsoftのインデックス再構築と再構築に関するドキュメント は、フラグメントレベルを2つのSQL Server操作にマッピングしています:
-
5-30% フラグメント:
ALTER INDEX idx_name ON tbl_name REORGANIZEはオンライン操作として、葉レベルのページを段階的にコンパクト化します。実行中に中断してもインデックスが破損しません。 -
30%を超える場合:
ALTER INDEX idx_name ON tbl_name REBUILDインデックスを再作成します。デフォルトでオフライン(スキーマ変更ロックを取得して、同時アクセスをブロックします)。追加WITH (ONLINE = ON)はエンタープライズエディションで再構築中にインデックスを利用可能に保ちます。オンライン再構築でも操作の開始と終了時に一時的にスキーマ変更 (Sch-M) ロックを取得し、通常は数ミリ秒ですが、非常に高い並列処理負荷では認識可能な待ち時間を引き起こすのに十分長いことがあります。
SQL Server 2017以降では、ONLINE = ON と RESUMABLE = ON を組み合わせ、設定可能なMAX_DURATION で長い再構築を一時停止および再開する: ALTER INDEX idx_name ON tbl_name REBUILD WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 60)。ALTER INDEX idx_name ON tbl_name REBUILD WITH (RESUME) で再開する。RESUMABLE = ON には ONLINE = ON が必要であり、SQL Server 2017 ではエンタープライズエディション限定である;SQL Server 2019 以降は Standard および Web エディションでも有効にするため、この構文を使用する前にエディションを確認してください。
The 5% の床は同等に重要である 3%のフラグメンテーションがあるインデックスに対してREORGANIZEを実行すると、ログ活動が発生し、I/Oを消費し、可測定可能なクエリの改善は生じません。
PostgreSQLの場合、VACUUM は死んだタプルのストレージを回収し、可視性マップを更新します。ANALYZE はプランナーの統計情報を更新します。REINDEX は物理的なインデックスのボリュームが確認された時にB-ツリー構造を再構築します
VACUUM VERBOSE ANALYZE transactions;
-- Blocking rebuild (requires maintenance window):
REINDEX INDEX transactions_created_at_idx;
-- Non-blocking rebuild (PostgreSQL 12+):
REINDEX INDEX CONCURRENTLY transactions_created_at_idx;
REINDEX CONCURRENTLYはトランザクションブロック内で実行できず、標準形式よりも時間がかかりますが、再構築中に書き込みを続けることを可能にします。即時の修正を超えて、VACUUM VERBOSE定期的に、あなたの最も書き込みの多いテーブルで出力を確認する必要があります。それは、デッドテンプレートのカウント、ページ再利用データ、およびクリーンアップ統計を提供し、これらはテーブルの健康状態を示す間接的なサインを与えます。PostgreSQLのautovacuumはルーチンデッドタプルのクリーンアップを処理します自動的に、しかし高負荷の削除作業では遅れてしまう。公式のPostgreSQLドキュメントでは、ルーチン真空掃除のチューニングについて説明されている。autovacuum_vacuum_scale_factor と autovacuum_vacuum_threshold は、デフォルトがあまりにも保守的であるテーブルに対して使用されます。
MySQLの場合、OPTIMIZE TABLE はテーブルスペースをフラグメント化し、統計情報を1つの操作で再構築します。MySQL 8.0以降では、通常のInnoDBテーブルに対してオンラインで実行され、準備段階とコミット段階でのみ短いメタデータロックが発生しますが、大きなテーブルでは完全なコピーに相当な時間がかかることがあります:
OPTIMIZE TABLE events;
ANALYZE TABLE events;
内部では、InnoDBはOPTIMIZE TABLEをALTER TABLE ... FORCEにマップし、クラスタインデックスとすべてのセカンダリインデックスを再構築します。大規模なテーブルでのダウンタイムなしの実行のためには、Percona Toolkitのpt-online-schema-changeが同じ再構築を行いながら元のテーブルを動作させます:
pt-online-schema-change \
--alter "ENGINE=InnoDB" \
--execute \
D=app_prod,t=events,h=127.0.0.1,F=$HOME/.my.cnf
シャドウコピーを維持し、再構築中にトリガーを通じて書き込みを再生します。--executeフラグが必要です;それがないと、ツールはドライランモードのみで実行されます。
症状の重症度による修正措置の検索:
| 症状の重症度 | エンジン | ダウンタイム許容度 | 推奨アクション |
|---|---|---|---|
| 軽度(frag < 5% / 死亡率 < 10%) | すべての | N/A | なし |
| 中程度 (5-30%) | SQL Server | どれでも | ALTER INDEX ... REORGANIZE |
| 重篤 (> 30%) | SQL Server | 必要 | インデックス...を再構築する (ONLINE=ON) [Enterprise] |
| 深刻 (> 30%) | SQL Server | 利用可能 | インデックス...を再構築 |
| 高設定 (dead_pct > 10%) | PostgreSQL | どれでも | 真空分析 |
| 高い肥大(free_percent > 30%) | PostgreSQL | 必要 | 同時再インデックス |
| 高まっている(frag_pct > 20%) | MySQL | 利用可能 | テーブルを最適化 |
| 上昇 (フラグメントパーセンテージ > 20%) | MySQL | 必要 | pt-online-schema-change |
フラグメントが解消された後、次にクエリが遅くなる原因となるのは古い統計情報で、これは最適化器がインデックスの検索よりも何桁も速いスキャンを選択させることを引き起こします。
症状: クエリプランの回帰
実行プランには昨日、インデックスのスキャンが行われたテーブルスキャンが示されており、最適化器は変更されていません。それが頼っているデータは変更されました。これは統計情報の問題です.
古くなった統計情報の診断
SQL Server 最適化器は行数の見積もりとデータ分布のヒストグラムを使用しますが必要です。これらの統計情報が急成長するテーブルで数週間古い場合、最適化器は検索よりも劇的に速いスキャンを選択します。UPDATE STATISTICS table_name WITH FULLSCANを実行して、大量のバッチロードを受け取るテーブルを確認してください。WITH SAMPLEのバリアントは、大きなテーブルで偏った分布を見逃す可能性のある行サンプリングパーセンテージを使用しており、現在の統計情報に見えるが代表していないサブセットを反映しています。
古い統計情報や悪いプラン選択に苦しむインデックスを検出するには、sys.dm_db_index_usage_statsをクエリします:
SELECT OBJECT_NAME(object_id) AS tbl_name,
index_id,
user_seeks,
user_scans,
user_lookups
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID()
ORDER BY user_scans DESC;
ゼロの検索回数で高いスキャン回数があるインデックスは、統計情報の更新や欠落しているインデックスの評価の候補です。
PostgreSQLのANALYZEコマンドとMySQLのANALYZE TABLE独立にプランナーの統計情報を更新するVACUUMそしてOPTIMIZE TABLEそれぞれ。PostgreSQLでは、autovacuumが実行されます。ANALYZE自動的に後に変更可能な行の割合コントロールされていますautovacuum_analyze_scale_factor、デフォルトは0.1または10%ですが、そのデフォルトは大きなテーブルには高すぎますは、2億行のテーブルは20万行の変更が必要です。それにより、オートバキュームのANALYZEパスがトリガーされ、その時点でクエリプランは数時間間違っている可能性があります。autovacuum_analyze_scale_factorを0.01に下げたり、autovacuum_analyze_thresholdを使用してテーブルごとのオーバーライドを行うことで、これを解決できます。
状況を中断せずに統計情報を更新
SQL ServerではUPDATE STATISTICS は通常クエリをブロックしません(データの読み取りには NOLOCK メタニクスを使用します)。ただし、高負荷シナリオでのクエリコンパイル中に非同期統計更新が一時的なスキーマロックの競合を引き起こすことがあります。影響を受けるテーブルのキャッシュされた実行計画を無効にします:その直後、SQL Server は次の実行時に計画を再コンパイルし、更新されたテーブルに対する多くの並行クエリがあるシステムでは一時的に CPU 使用量が増加する可能性があります。重くクエリが行われるテーブルでは、低トラフィックのウィンドウ中に実行します。選択肢はFULLSCAN と SAMPLE はテーブルサイズと分布スキューに依存します。
小規模から中規模のテーブルの場合、FULLSCAN は通常、オフピーク時間に実行するのに十分早く完了します(実用的な上限はハードウェアに依存しますが、多くのチームは約1000万行を経験則的な切断点として使用します)。より大きなテーブルの場合、より高いサンプルパーセンテージ(例えば SAMPLE 20 PERCENT やSAMPLE 30 PERCENTは、デフォルトのサンプルよりも精度と時間のトレードオフが良い場合がありますが、最適な割合はワークロードによって異なります。
PostgreSQLでは、ANALYZEは設定可能なサンプルを読み取ります(デフォルトはdefault_statistics_target = 100、つまり各列30,000行を意味し)、テーブルをロックしません。バッチロードやパーティションスワップ後に手動で実行してください。
MySQLではANALYZE TABLE は InnoDB 上で行われる軽量な操作であり、インデックスツリーのランダムなサンプリングを読み取ります。高速な操作です:MySQL 8.0 以降では、ANALYZE TABLE はオンライン DDL 意味を使用し、以前のバージョンで必要だった完全な読み取りロックを回避します。代表するクエリの前後で EXPLAIN をキャプチャして、プランナーが新しい統計情報を取得したことを確認します。
OpManager Nexusは、歴史的なベースラインと比較してオンプレミスでクエリプランの回帰検出を自動化し、異常フラグを設定します。同じ機能は、そのSaaS配信を通じてクラウド管理型データベースにも拡張され、スロークエリログ分析は、設定可能な実行時間の閾値を超過するクエリに掘り下げます。以下の自動修正セクションでは、その検出を修正ワークフローに接続する方法について説明します。
統計的障害はクエリプランが劣化するまで目に見えません。ストレージの障害も同様に静かで、ディスクが満杯になりデータベースがオフラインになるまで分かりません.
症状:ストレージ圧力と無制限な成長
85%の容量でディスク使用量アラートが発生しました。データベースサーバーは何ヶ月も運用されており、誰もログファイルやテーブルスペースの成長速度を確認していません。根本原因は二つのカテゴリーに分かれます:管理されていないトランザクションログの成長とアーカイブ戦略の欠如。どちらもメンテナンスの失敗であり、モニタリングは数週間前にこれを検知すべきでした。
トランザクションログとWAL管理
SQL Server: は 完全復旧モデルのデータベースで、定期的なトランザクションログバックアップがない場合、 はそのログファイルがディスクが満杯になるまで成長し、完全なデータボリュームは即座に生産停機となります。現在のログスペース使用状況をすべてのデータベースについて確認するには、DBCC SQLPERF(LOGSPACE); を実行し、これは各データベースのログサイズ、使用スペースの割合、および状態を返します。単一のデータベースの場合、sys.databases をクエリしてlog_reuse_wait_desc 列は、ログが切り詰められない正確な理由を教えています(例えば、LOG_BACKUP、ACTIVE_TRANSACTION)。ログバックアップのスケジュールは、ご自身の復旧ポイント目標(RPO)に合わせた間隔で行ってください:ほとんどのOLTPワークロードでは、5-30分の間隔が一般的に使用され、高トランザクションシステムではより短い間隔が使用されますが、適切な頻度はワークロードによって異なります。
DBCC SHRINKFILE はログファイルにおいて予期せぬログ成長イベントの後のスペースの回収のための最終手段です。それは定期的なクリーンアップツールではなく最終手段である理由は、仮想ログファイルへの副作用があるからです。 (VLFs)、SQL Server がトランザクション ログを分割する内部セグメント。各縮小後に再拡大するサイクルは新しい VLF を追加するため、繰り返し縮小されたログは少数の大きなものではなく、多くの小さな VLF にフラグメント化して終わる。そのフラグメント化は順次ログ書き込みのスループットを低下させ、回復時間を増加させる。 は、根本的な原因(ログバックアップの欠如、長時間実行中のトランザクション)に対応することで解決するものであり、スケジュールに基づいて縮小することではない。
PostgreSQL: WAL(Write-Ahead Log) の管理は、SQL Server のトランザクションログと同じ機能を提供します。archive_mode と archive_command の設定は、完了した WAL セグメントがアーカイブストレージに送信されるかどうかを制御します。アーカイブが有効になっていない場合、WAL セグメントは蓄積しますインpg_wal/ディスクが満杯になるまで。wal_keep_sizeパラメータ (PostgreSQL 13+, 取代)wal_keep_segments保持 WAL データの保持に最低限の基準を設定しますが、成長を制限しません。プロダクションシステムの場合は、継続的なアーカイブを設定します。archive_mode = onそして指すarchive_command あなたのバックアップインフラストラクチャ(pgBackRest、Barman、またはクラウドネイティブな同等品)へ。
アーカイブがアクティブで最新かどうかを確認するには:SELECT * FROM pg_stat_archiver; last_archived_wal タイムスタンプと failed_count を確認してください。ゼロ以外の failed_count または古くなった last_archived_time は、WALセグメントが蓄積していることを意味します。また:SELECT count(*), pg_size_pretty(sum(size)) FROM pg_ls_waldir(); (PostgreSQL 10+) は、WALディレクトリの合計サイズを表示します。
MySQL: バイナリログ (binlogs) はリプリケーションとポイントインタイムリカバリーに役立ちます。ローテーションがないと、無限に成長します。expire_logs_days (MySQL 8.0.3で非推奨) または binlog_expire_logs_seconds (MySQL 8.0+) は自動削除を制御します。binlog_expire_logs_seconds = 604800 を設定すると、7日間のバイナリログが保持され、大多数のリプリケーション構成には十分です。PURGE BINARY LOGS BEFORE NOW() - INTERVAL 7 DAY を一度だけ実行してクリーンアップします。
OpManager Nexusによる容量予測
85%のディスクアラートに反応することは、計画された行動のための余地をほとんど与えません。OpManager NexusのAI/MLベースのストレージ予測は、最大14日間の履歴を使用して、ストレージが80%、90%、および100%に達する時期を予測し、少なくとも3日間のデータがある場合にチームに「N日後にディスクが満杯になる」という信号を与えます。その適応的閾値 は、本物の異常ではなく、毎回のバッチジョンではなく、真の異常発生時にアラートが発生するようにベースライン行動を学習します。また、データベースタブは個々のデータベースサイズ、データおよびログファイルの利用状況と成長傾向を表示します.
注意: OpManager Nexusの監視データ保持(設定は設定>全般設定> データベースのメンテナンスは、あなたの生産用データベースのストレージとは独立しています。デフォルトは、詳細、毎時、毎日の統計のための7日間、30日間、365日間です。
OpManager Nexusの予測レポートを使用して、あなたのアーカイブのサイクルが成長に合わせていますかを確認してください:予測が30日後に80%の容量を示す場合でも、あなたのアーカイブジョブが月に1回実行される場合、頻度を増やすか、もっとストレージを確保してください。
ストレージ圧力は時間の経過とともに蓄積する受動的な障害です。ロック競合は能動的な障害です:データベースを修正するためのメンテナンス操作が事象の原因となります。
症状:メンテナンス操作からのロック競合
スケジュールされたメンテナンス実行直後にブロックされたセッションの急増は、REBUILDまたはREORGANIZEが生産トラフィックと衝突したことを直接示しています。がロックの競合を生成しました。メンテナンスジョブは性能を修正するはずですが、ピーク時トラフィック中やメンテナンスウィンドウなしでONLINE = ONなしで実行されるインデックスのREBUILDは、同時クエリをブロックするロックを保持し、修正を事態に変えてしまいます
。メンテナンスによるブロッキングの特定
メンテナンス時期をOpManager Nexusのセッションタブと関連付けることで、メンテナンスによるブロックとアプリケーションレベルの競合を区別できます。メンテナンスウィンドウが開いて数分以内にブロックされたセッションの数が急増した場合、そのメンテナンスジョブが原因です。SQL Serverでは、sys.dm_exec_requestsでwait_type値がLCK_M_*で始まるセッションを確認し、チェーンの先頭にあるブロッカーを検索してその詳細を確認してください。command 列は ALTER INDEX または DBCC 操作のために使用されます。
PostgreSQLでは、pg_stat_activityはLockの待機イベントを表示し、wait_eventの値としてrelationやtransactionidが表示されます。もしブロッキングPIDがREINDEXを実行している場合、VACUUM FULLはメンテナンスによる競合です。セッションタブへのアクセスが利用できないクラウド管理インスタンスの場合、OpManager NexusのSaaS配信はロック競合を表面化し、同じ分類信号に対してデータベースのパフォーマンスダッシュボード上でブロックセッションの数を表示します。
オンラインおよび再開可能な操作
修正は実行可能です:オンライン操作を使用し、ピークトラフィックウィンドウ外でスケジュールします。
SQL Server: I/O劣化セクションで説明されているようにALTER INDEX ... REBUILD WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 60)を使用します。期間は分単位の正の整数で、メンテナンスウィンドウに基づいて設定します。REORGANIZEは常にオンラインであり、中断可能です。
PostgreSQL: REINDEX INDEX CONCURRENTLY (I/O劣化セクションで導入) は排他ロックを回避します。VACUUM は FULL なしで読み書きをブロックしません。
MySQL: 標準の OPTIMIZE TABLE は MySQL 8.0+ でオンラインDDLとしてすでに実行されています (I/O劣化セクションで導入)。pt-online-schema-change とても大きなテーブルでロックの期間をより細かく制御する必要がある場合、または OPTIMIZE TABLE が提供しないトリガーされたシャドウコピーの意味論を望む場合、
です。上記の四つの症状カテゴリはすべて、アウトアゲインになる前に観測可能なパフォーマンスシグナルを生成します。 corruptio は異なります:それがクエリの失敗やデータの損失として表面になるまで、シグナルを生成しません。
症状:静寂的な corruptio と整合性の失敗
汚職は予兆待機イベントや遅延のずれを生み出さないため、検出は意図的にスケジュールされた行為であり、アラートへの対応ではない。定期的な整合性チェックが主要な検出メカニズムであり、ストレージレベルのチェックサム、ページ検証、信頼できるバックアップで補完される。
SQL Server: DBCC CHECKDB は ページ汚職、割り当てエラー、整合性違反 を検出する。
-- Recommended production form: suppresses informational messages, shows only errors
DBCC CHECKDB('ProductionDB') WITH NO_INFOMSGS, ALL_ERRORMSGS;
大規模なデータベースでは、フルDBCC CHECKDBがメンテナンスウィンドウであまりにも遅すぎると、DBCC CHECKDB ... WITH PHYSICAL_ONLYは論理整合性チェックなしでページとレコードヘッダーの整合性をチェックし、大幅に高速に完了します。損傷はSQL ServerエラーログにメッセージとしてMsg 823、824、または825として表面化します。 は知られている破損イベントを積極的に確認するには、疑わしいページテーブルをクエリします:
SELECT db_id, file_id, page_id, event_type, error_count, last_update_date
FROM msdb.dbo.suspect_pages
WHERE event_type IN (1, 2, 3);
イベントタイプ 1 = 823/824 エラー、2 = 不正なチェックサム、3 = 撕れたページ。空でない結果は、直ちに DBCC CHECKDB と復元計画が必要です。
DBCC CHECKDB を可能な限り頻繁に実行することが安全な方法です。多くの専門家はすべてのデータベースにおいて日次を推奨しています。それは実用的でない場合、重要なデータベースを優先し、WITH PHYSICAL_ONLYを使用して大きなものの間隔を短縮します。
PostgreSQL:pg_amcheck ユーティリティ(PostgreSQL 14以降)は、インデックスエントリによって参照されるすべてのヒープタプルが実際に存在し、インデックスエントリが正しいソート順に並んでいるかを確認することで、B-ツリーインデックスの整合性を検証します。デフォルトの実行は通常のスケジュールされたチェックに十分速く、大多数の破損を検出します:
pg_amcheck mydb
予期せぬクラッシュ、ストレージイベント、またはリプレイ失敗後、重要なテーブルに対して徹底的なバリエーションを実行します:
pg_amcheck --heapallindexed --parent-check mydb
--heapallindexedは、すべてのヒープタプルが対応するインデックスエントリを持っているかどうかのより深いチェックを実行します;--parent-check はクロスレベルB木の不変量を検証します。両方のフラグは実行時間を大幅に増加させるため、インシデント対応やイベント後の検証のために、日常のスケジュールではなくそれらを予約してください。
MySQL: mysqlcheck はテーブルレベルの整合性検証を提供します:
mysqlcheck --check --all-databases -u root -p
個々のテーブルの場合、CHECK TABLE table_name は MySQL クライアント内で同じ操作を実行します。InnoDB テーブルは、メジャーバージョンアップ後に CHECK TABLE ... FOR UPGRADE を利用してストレージ形式の互換性を確認することで利益を得ます。
これらのチェックを手動で実行することは安全策です。次のセクションでは、プラットフォームがオンボールエンジニアがログインする前に対応するように応答を自動化する方法を示します。
アラートから修正まで:エンジン間の自動修正
午前3時にアラートが発生した場合、プラットフォームが修復を自動的に実行することは、修復方法を知るよりもずっと重要です。OpManager NexusのITワークフロー自動化は、アラートの閾値を超えた際にカスタムモニタリングスクリプトをトリガーします:スクリプトは症状の診断表面(フラグメント化、デッドテーブル行、ログスペース)をクエリし、深刻度を評価し、修復を実行します.
SQL Server: OpManager Nexusに修復を接続
OpManager NexusはPowerShellやshellスクリプトをカスタムモニターとして受け付けます (カスタムスクリプトモニターはビルド12.7以降が必要です)。統合パターンは以下のPostgreSQLとMySQLの例に一致します:sys.dm_db_index_physical_statsでフラグメンテーションをクエリ、閾値で分岐、ALTER INDEX REORGANIZEを発行しますREBUILD WITH (ONLINE = ON) に従い、各アクションごとに1行のログを出力するようにして、実行がモニターの履歴に表示されるようにします。ターゲットデータベースで最低限 db_ddladmin のサービスアカウントでスクリプトを実行します;SQL認証やクロスドメイン設定の場合は、シークレットストアから資格情報を引き出す代わりに、それを埋め込みません.
PostgreSQLとMySQLのシェル自動化
PostgreSQLの場合、cron駆動のシェルスクリプトでクエリpg_stat_user_tables は、膨らんだテーブルとトリガーの修正に使用されます:
#!/usr/bin/env bash
# PostgreSQL automated vacuum/reindex for tables exceeding dead tuple threshold.
# Credentials sourced from ~/.pgpass (chmod 600); export PGPASSFILE if non-default.
PGHOST="localhost"
PGPORT="5432"
PGDATABASE="app_prod"
PGUSER="maintenance_user"
export PGPASSFILE="${PGPASSFILE:-$HOME/.pgpass}"
DEAD_THRESHOLD=15
BLOAT_THRESHOLD=30
# VACUUM tables with high dead tuple ratio
psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGDATABASE" -t -A -F'|' -c "
SELECT schemaname, relname, round(n_dead_tup::numeric / NULLIF(n_live_tup + n_dead_tup, 0) * 100, 2)
FROM pg_stat_user_tables
WHERE n_live_tup > 10000
AND round(n_dead_tup::numeric / NULLIF(n_live_tup + n_dead_tup, 0) * 100, 2) > $DEAD_THRESHOLD
" | while IFS='|' read -r schema table dead_pct; do
echo "$(date '+%Y-%m-%d %H:%M:%S') | VACUUM ANALYZE ${schema}.${table} | dead_pct=${dead_pct}%"
psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGDATABASE" -c "VACUUM ANALYZE ${schema}.${table};"
done
MySQLの場合、類似のアプローチは information_schema.TABLES をクエリし、OPTIMIZE TABLE をトリガーします。スクリプトに認証情報を埋め込む代わりに、MySQLのオプションファイルを使用します(~/.my.cnf を [client] 認証情報で作成し、パーミッションを600に制限します)。
#!/usr/bin/env bash
# MySQL automated optimize for InnoDB tables exceeding fragmentation threshold
MYSQL_HOST="localhost"
MYSQL_DB="app_prod"
FRAG_THRESHOLD=20
mysql --defaults-extra-file="$HOME/.my.cnf" -h "$MYSQL_HOST" -N -B -e "
SELECT table_name, round(data_free / (data_length + index_length + data_free) * 100, 2) AS frag_pct
FROM information_schema.TABLES
WHERE table_schema = '${MYSQL_DB}'
AND engine = 'InnoDB'
AND data_free > 0
AND round(data_free / (data_length + index_length + data_free) * 100, 2) > ${FRAG_THRESHOLD}
" | while read -r table frag_pct; do
echo "$(date '+%Y-%m-%d %H:%M:%S') | OPTIMIZE TABLE ${table} | frag_pct=${frag_pct}%"
mysql --defaults-extra-file="$HOME/.my.cnf" -h "$MYSQL_HOST" "$MYSQL_DB" -e "OPTIMIZE TABLE ${table};"
done
cron を通じてスクリプトのいずれかをスケジュールする(例:0 3 * * * /opt/scripts/pg_maintenance.sh >> /var/log/db_maintenance.log 2>&1)し、OpManager Nexus のカスタムモニタリング統合を通じてログ出力を監視する.
クラウド管理型データベース自動化
Amazon RDS、Aurora、またはAzure SQLで実行されているデータベースの場合、OpManager NexusのSaaS提供は上記のPowerShellおよびシェル自動化パターンのクラウド側の対応物を提供します。そのIT Automationモジュールは、閾値違反や異常検知から修正アクションをトリガーし、AIによるベースラインを提供します。 は、セルフマネージドインスタンスが要求する手動の閾値調整を置き換えます。RDSに特化して、サービスアクション として起動、停止、フェイルオーバー再起動が直接表示されます。エンジン固有のモニタリング設定 は SQL Server、PostgreSQL、MySQL 用に別途ドキュメント化されています。閾値プロファイルは、開発、ステージング、本番のモニター間で同等のアラート設定を適用できるようにします。そのため、現実的なステージングの負荷でインデックスをフラグメント化するクエリは、本番スケールに達する前にスロークエリ検知に現れることになります。
メンテナンスヘルススコアカード:現在のポジショニングを評価します
既存の診断クエリをすべてやり直す代わりに、このスコアカードを使ってメンテナンスの状況を評価してください。各項目は上記の対応するセクションで説明されている診断方法を参照しています。
I/Oの健康状態(参照:I/O劣化セクション)
- [ ] SQL Server:
sys.dm_db_index_physical_statsクエリを実行します(結果を30%のフラグメンテーションでフィルタリング)。返されるインデックスの数:___ - [ ] PostgreSQL:
pg_stat_user_tablesが死亡したタプルのクエリを実行します。dead_pct が 10-20% を超えるテーブルは、すぐに注意が必要です: ___ - [ ] MySQL:
information_schema.TABLESの断片化クエリを実行します。frag_pct が 20% を超えるテーブル: ___
統計情報の新鮮さ(Query Plan Regressionセクションを参照)
- [ ] SQL Server: 検証
sys.dm_db_index_usage_statsは、ゼロの検索回数だが高いスキャン回数があるインデックス(プランの回復または不適切にマッチしたインデックス)に対して使用します - [ ] PostgreSQL: 100百万行を超えるテーブルに対して、
autovacuum_analyze_scale_factorが 0.1 より小さいことを確認します - [ ] MySQL: 書き込み量が高い上位10テーブルに対して
ANALYZE TABLEを実行し、代表するクエリの前後でEXPLAINの出力をキャプチャして、プランナー統計が期待通りに変更されたことを確認します
ストレージの軌跡(参照:ストレージ圧力セクション)
- [ ] OpManager Nexus予測レポートは、いかなる閾値の超過も前に十分な容量があることを確認します:はい / いいえ
- [ ] トランザクションログバックアップジョブ(SQL Server)またはWALアーカイビング(PostgreSQL)が実行され、最後のバックアップが検証されました:はい / いいえ
- [ ] バイナリログローテーション(MySQL)が設定されています
binlog_expire_logs_secondsは明示的な値に設定されます: はい / いいえ
完全性のベースライン(参照:静的 corruption セクション)
- [ ] SQL Server:
DBCC CHECKDB重要なデータベースでの最終実行日付: ___ - [ ] PostgreSQL:
pg_amcheck最終実行日付(または同等の手動チェック): ___ - [ ] MySQL:
mysqlcheck --check最終実行日付: ___
自動化カバレッジ(参照:自動修復セクション)
- [ ] 少なくとも1つの自動修復スクリプトがデプロイされ、スケジュールされ、出力ログが生成されていることを確認:はい / いいえ
- [ ] OpManager Nexusのアラート閾値が、主要なデータベースヘルスメトリクス(BCHR、ディスク利用率、ブロックされたセッション)に対して設定およびテストされている:はい / いいえ
- [ ] メンテナンスウィンドウは監視信号に基づいてスケジュールされ、カレンダー日付ではありません:はい/いいえ
その結果をOpManager Nexusの遅いクエリとセッションデータ(オンプレミスのパフォーマンスタブまたはSaaSデータベースメトリクスダッシュボード)と照合してください。トップ結果のサイズで上位にあるテーブルが遅いクエリ検知のソースとしても表示される場合、それがあなたの最優先度の高いメンテナンスターゲットです。











