採用情報 お問い合わせ

BLOG

Zabbix で保存期間を短縮してもデータが減らない・容量が空かない理由と解決策

はじめに :

Zabbix を運用していて監視データが想定以上に膨れ上がり、HDD 容量が逼迫した際、ヒストリやトレンドの保存期間を短縮したり、不要なホストやアイテムを削除したりしても、「なかなかデータの削除が進まない」「削除されたはずなのに容量が空かない」といったお問い合わせをいただくことがあります。

この事象は、Zabbix の housekeeper(データ削除機能)に 1 回の処理に上限が設けられていることや、データベースの特性上、単に DELETE 文でデータを削除しただけでは OS 上のディスク容量が解放されないことに起因します。そもそも、巨大化してしまったテーブルに対して大量の DELETE 文を発行するため、処理自体に多大な時間を要し、システム全体のパフォーマンス低下を招くことも少なくありません。

そうした課題を抜本的に解決する手段として、DB パーティショニングを利用する方法があります。
本記事では、housekeeper によるデータ削除の内部的な挙動を紐解きながら、MIRACLE ZBX に標準実装されている MariaDB のテーブルパーティショニング機能を利用した解決アプローチについて解説します。

※ 本記事で使用する用語についてはこちらの用語集を参照してください。

環境 :

MIRACLE ZBX 7.0.24

ケース 1:保存期間を短くしてもデータがなかなか減らない

【事象】

監視データの保存期間を「6 ヶ月」から「2 週間」へ大幅に短縮したにもかかわらず、設定した期間まで削除が追いつかないケースです。

【原因】

Zabbix の housekeeper プロセスによるデータ削除処理には、一度に大量のデータが削除されることによるデータベースへの負荷を防ぐため、1 回あたりの削除範囲に上限があるためです。
具体的には、1 回 housekeeper が実行されるごとに、最大でも「実行間隔の 4 倍(デフォルトなら 4 時間分)」の過去データしか削除されません。そのため、数ヶ月分のデータを削除するには相応の日数が必要です。

【どれくらい時間がかかるのか?(具体例)】

保存期間を「180 日」から「14 日」に変更し、166 日分のデータを削除する場合を試算します。

設定・前提 : HousekeepingFrequency = 1(1 時間に 1 回実行)

1 回の実行で消せるのは、実行間隔(1 時間)の 4 倍にあたる 4 時間分のみです。そのため、1 日分(24 時間)のデータを消すだけでも 6 回(24 ÷ 4)の実行が必要となります。したがって、166 日分をすべて消し切るには、最低でも 996 回(166 日 × 6 回)の housekeeper 処理(時間にして 996 時間=約 41.5 日)が必要になります。

【対処方法】

以下の 2 つのアプローチがあります。

1. 気長に「待つ」

特別な操作をせず放置した場合でも、housekeeper は 1 日に 24 回自動実行されます。(HousekeepingFrequency = 1 前提)1 日経過するごとに「過去データ 4 日分」が削られ、新たに増える「現実の 1 日分」を差し引いても、実質 1 日あたり 3 日分の遅れを取り戻せます。上記の例(166 日分の遅れ)の場合、完全に追いつくまでには約 55 日(166 ÷ 3)ほどかかります。ディスク容量にまだ余裕がある場合は、このまま待つのが最も安全です。

2. RTC(ランタイムコントロール)で強制実行する

「数十日も待てない!」という場合は、コマンド(zabbix_server -R housekeeper_execute)を実行して手動で housekeeper をキックし、処理ペースを早めることができます。

  • ただし強制実行の場合でも「1 回につき最大(最低)4 時間分」というロジックは変わらないため、手動(またはスクリプト)で約 996 回コマンドを実行する必要があります。
  • 注意点(重要)
    RTC による強制実行を連続で行うことは、データベースへの負荷の観点で非常に危険です。必ずディスク I/O や負荷(CPU 使用率、ロードアベレージ等)をモニタリングしながら、適切な間隔を空けて実行してください。

【housekeeper の内部ロジックと RTC 実行時の挙動(詳細)】

Zabbix のソースコード実装では、「現在の最古データの時刻 + (housekeeper プロセスのスリープ時間 × 4)」と「保存すべき最古の時刻(現在時刻 - 保存期間)」を比較し、古い方の時刻までのデータを削除します。
この「スリープ時間」は、「前回の処理完了時から今回の処理開始時までの実際の経過時間」を指します。通常時は HousekeepingFrequency の設定値と同等ですが、RTC コマンドを用いて 1 時間未満の間隔で強制割り込みを実行した場合、経過時間は「1 時間」として切り上げ処理されます。つまり、コマンドを数分おきに連打したとしても、1 回の実行で進む削除時間は「4 時間分」となります。

  • 重要:OS のディスク容量(空き領域)について 本ケースの手順によって、過去データが削除されたとしても、OS 上のディスク空き容量は増えません。ディスク容量を物理的に確保したい場合は、「ケース 3」をご参照ください。

ケース 2:アイテム、ホストを削除しても監視データが即座に消えない

【事象】

Zabbix の Web フロントエンド画面上から不要になったホストやアイテムを削除したにもかかわらず、データベース内の論理的な容量(過去データのレコードの件数等)が即座に減らないため、「本当にデータが削除されたのか?」と懸念してしまうケースです。

【原因】

Web フロントエンドからホストやアイテムの監視設定を削除しても、それに紐づく過去の監視データは即座には削除(DELETE)されない実装となっているためです。
ユーザが削除操作を行うと、Zabbix は対象の「設定データ」のみを即座に削除し、「過去の監視データ」の削除タスクは内部の「housekeeper テーブル(削除待ちキュー)」に一旦登録します。その後、Housekeeper プロセスが HousekeepingFrequency の間隔で起動した際に、設定された上限値(MaxHousekeeperDelete)ずつ、対象のデータを小分けにして徐々に DELETE していく仕組みになっています。

【対処方法】

以下の 3 つのアプローチがあります。

1. 気長に「待つ」

Housekeeper がバックグラウンドで徐々に(MaxHousekeeperDelete を上限に)監視データが削除されます。特別な操作は必要ありません。最も安全な方法です。

2. RTC(ランタイムコントロール)で強制実行する

急いでキューを消化させたい場合は、ケース 1 と同様に Zabbix サーバー上で以下のコマンドを実行し、手動で housekeeper をキックできます。

  • ただし、1 回のコマンド実行で削除されるのは、設定ファイルで定義された MaxHousekeeperDelete の件数分のみです。
# zabbix_server -R housekeeper_execute 
3. 1 回あたりの削除件数を増やす

Zabbix サーバーの設定ファイル(zabbix_server.conf)にある MaxHousekeeperDelete の値を引き上げることで、housekeeper が 1 回の処理で削除する件数を増やすことが可能です。

  • 注意点(重要)
    この値を極端に増やしたり、無制限(0)に設定したりすることは推奨されません。1 回で発行される DELETE 文の行数が膨大になり、データベースが過負荷状態に陥るリスクが非常に高くなります。変更する場合は DB の負荷(CPU 使用率、I/O 待機率など)を見ながら慎重に調整してください。
  • 重要:OS のディスク容量(空き領域)について 本ケースの手順によって内部キューが消化され、過去データが削除されたとしても、OS 上のディスク空き容量は増えません。ディスク容量を物理的に確保したい場合は、「ケース 3」をご参照ください。

ケース 3:housekeeper がデータを削除しても OS 上の空き容量が増えない

【事象】

Zabbix の housekeeper プロセスが正常に動作し、古い監視データは確実に消えているはずなのに、OS 上で df コマンド等を実行してもディスクの空き容量が全く増えない事象です。

【原因】

これは Zabbix の問題ではなく、裏側で動いているデータベース(MariaDB/MySQL の InnoDB など)のアーキテクチャ上の仕様が原因です。
(※ 以下は主に MariaDB/MySQL の「InnoDB」ストレージエンジンを前提とした解説です。)
housekeeper はデータを「DELETE 文」で削除します。InnoDB の内部仕様では、データが削除されると、その領域は「次回新しいデータが書き込まれた際に再利用する空き領域(または空きページ)」として DB 内部のリストに回収・管理されます。そのため、DB 内のデータ量は減っても、OS に対してファイルサイズが自動的に縮小され(物理的な容量が返却され)ることはありません。加えて、大量のデータ追記と DELETE が繰り返されると、データ領域内に「空きスペース」が散らばる(内部断片化)だけでなく、ファイル内部でデータの物理的な連続性が失われていきます(外部断片化)。これを「フラグメンテーション(断片化)」と呼びます。
フラグメンテーションが発生すると、データ密度の低下や不要なディスクシークの増加により、ディスクの I/O 性能が著しく劣化する現象が発生します。

【対処方法】

内部の空きスペースを詰め直し、OS に容量を返却してディスクの空きを物理的に増やすには、以下のいずれかの作業を行う必要があります。

1. テーブルの最適化(MariaDB/MySQL の InnoDB 環境の場合)

対象のテーブルに対して OPTIMIZE TABLE や ALTER TABLE ... ENGINE=InnoDB などのコマンドを実行し、データファイルを綺麗に再構成して空き容量を回収する標準的なアプローチです。

  • PostgreSQL 環境の場合は、VACUUM コマンドで同様の事象を解決することが可能です。ただし、対象テーブルに排他ロックがかかるため、コマンド実行中は事前に Zabbix サーバープロセスを停止しておく必要があります。無停止で容量を回収したい場合は、外部拡張ツールの pg_repack の利用ができます。
  • 注意 : この作業を実行するには、一時的な作業領域として「現在のテーブルサイズとほぼ同等のディスク空き容量」が追加で必要になります。
2. テーブルの再作成(ダンプ&リストア)

データを一度エクスポート(ダンプ)し、テーブルを作り直してから入れ直す方法です。
現在のデータをダンプ(エクスポート)してバックアップを取り、一度テーブルを DROP(削除)して OS に完全に容量を返却させた後、テーブルを作り直してデータをインポートする方法です。

  • 注意点
    数十 GB〜数 TB に肥大化したテーブルに対して ALTER TABLE などを実行すると、ストレージの I/O 性能によっては完了までに数時間から数日かかることもあります。その間は実質的に処理が詰まってしまうため、長時間のダウンタイムが避けられません。さらに、内部的には「新しいテーブルを作り直してデータを丸ごとコピーする処理」が行われます。そのため、実行時には OS のディスク上に現在の対象テーブルのデータ量と同等の一時的な空き容量が追加で必要になります。空き容量が不足している状態で実行すると、システムがクラッシュする恐れがあるためご注意ください。
  • 参考情報
    長期間使用していると DB の実使用量が増えます【MIRACLE ZBX 1.8, 2.0, 2.2】  

DB パーティショニングの仕組みとメリット

これまで紹介した対処方法は、どれも DB の負荷が上がる、ダウンタイムが発生する等課題が残ります。根本的な対処方法として DB パーティショニングがあります。

1. DB パーティショニングの特徴

DB パーティショニングとは、巨大な監視データを日毎などの単位で「物理的に別のファイル(パーティション)」に分けて蓄積していく仕組みです。

  • I/O の負荷が軽い : 「DELETE 文」による 1 行ずつの削除ではなく、古いデータが入ったファイルごと「DROP(破棄)」します。データベースにとって DROP は非常に軽量な処理であるため、システムへの負荷がほとんどかかりません。
  • 容量が即座に空く : ファイルごと削除するため、ケース 3 で解説したような「フラグメンテーション(断片化)」が発生しません。削除した瞬間に、物理的なディスク空き容量が即座に OS に返却されます。
2. MIRACLE ZBX におけるパーティショニング機能

本記事でご紹介する「MIRACLE ZBX」では、MariaDB を使用した DB パーティショニング機能をパッケージ標準でサポートしています。
これにより、以下のようなメリットがあります。

  • 自作の運用管理が不要 : MIRACLE ZBX 自体にパーティショニングを自動で管理(定期的な作成・削除)する機能が実装されています。そのため、運用回避のために cron などで自作のスクリプトを定期実行させるような、面倒でリスクのある作り込みは一切不要です。
  • 標準パッケージで動く : 特殊なデータベースやプラグインを別途用意する必要がなく、OS 標準の MariaDB パッケージをそのまま利用できるため、OS が標準でメンテナンスするパッケージを使用できます。
MIRACLE ZBX 仮想アプライアンス / 環境構築サービスで提供している機能です。
パーティショニングあり (DROP での削除 ) パーティショニングなし (DELETE 文での削除 )
日ごとのファイルが作成され、ファイルごと削除される。 フラグメンテーション(断片化)が発生し、内部的に空き領域としてマークされるだけで OS 上のデータファイルサイズは縮小されない。
※断片化状態はイメージです

どのくらい違うのか?

「パーティショニングあり」と「なし」で、実際にどれほどの差が出るのか。全く同じ構成のサーバを用意し、150 日分のデータ削除を行って比較検証してみました。

1. データ削除にかかる時間の違い

【パーティショニングなしの場合】

2527:20260615:223341.209 housekeeper [deleted 244 hist/trends, 259140000 items/triggers, 0 events, 0 problems, 0 sessions, 0 alarms, 0 audit, 0 autoreg_host, 0 records in 1971.056652 sec, idle for 1 hour(s)]
2527:20260615:233341.259 executing housekeeper

結果:約 32 分(1971 秒) DB に高い負荷がかかり続けました。

パーティショニングありの場合】

2807:20260616:021323.923 executing housekeeper
2807:20260616:021323.944 drop partition p20251211 from table history_uint
...
2807:20260616:021330.242 drop partition p20260515 from table history_uint

結果:約 6.5 秒(※短時間で処理が完了しました。)

2. OS 上のディスク容量(空き容量)の変化

削除処理の前後で du コマンドによるディスク使用量を確認しました。

削除前(共通)
12G /var/lib/mysql/zabbix/

【パーティショニングなしの場合】

# du -sh /var/lib/mysql/zabbix/
12G /var/lib/mysql/zabbix/

結果:減っていません。(内部で空き領域としてマークされただけで、OS には返却されません)

【パーティショニングありの場合】

# du -sh /var/lib/mysql/zabbix/
2.0G /var/lib/mysql/zabbix/

結果:即時に 10GB の容量が解放されました。

まとめ :

本記事では、Zabbix で保存期間を短縮してもデータがなかなか消えない・ディスク容量が空かない理由と、その解決策について解説しました。
Housekeeper の動作やデータベースの特性を正しく理解することは、安定した運用を行うために非常に重要です。

検証結果でもご覧いただいたとおり、肥大化したデータベース問題から解放される最も根本的な解決策は「DB パーティショニング」です。
しかし、稼働中の本番環境に対して手動でパーティショニングを後付けしたり、削除用のスクリプトを自作して管理し続けるのは、過去データの消失や障害のリスクが伴い、運用担当者にとって大きな負担となります。

これから構築・リプレースを検討される方へ

あらかじめ MariaDB のパーティショニング機能が最適化された状態で組み込まれている MIRACLE ZBX アプライアンス/環境構築サービスの活用がおすすめです。面倒なスクリプト自作や運用管理を行うことなく、導入直後から安全で快適な運用を開始できます。

すでに運用中で、肥大化した DB にお困りの方へ

「すでに何百 GB も溜まっているが、なんとかパーティショニング化して解決したい」という場合は、弊社のコンサルティングサービスにて後からの移行対応が可能なケースがございます。お気軽にご相談ください。

免責事項

本記事で紹介しているスクリプトや設定内容は、動作の仕組みを解説するためのサンプルです。実際の運用環境に適用する際は、ご自身の環境に合わせて十分にテストを行い、自己責任にてご活用ください。本記事の内容によって生じたいかなる損害についても、筆者は責任を負いかねます。

商標について

  • Zabbix は、ラトビア共和国およびその他の国における Zabbix LLC の登録商標です。
  • その他、本記事に記載されている会社名および製品名は、各社の商標または登録商標です。
本記事に関連するリンク