Zabbix でデータベースを監視しようとすると、テンプレート、Zabbix agent 2 のプラグイン、ODBC と方法がいくつもあり、どれを使えばよいか迷います。この記事では MySQL と PostgreSQL を例に、それぞれの方法の設定手順、テンプレートが見ている主なアイテムとトリガー、注文数やジョブの滞留のような業務データを監視するときの工夫と限界をまとめます。
内容は 2026 年 11 月時点で最新の LTS (長期サポート版) である Zabbix 7.0 の公式ドキュメントとテンプレートで確かめています。次の LTS の 8.0 はリリース候補の段階で、キーや設定の名前が変わる可能性があるので、8.0 を使う場合はそのバージョンのドキュメントも見てください。
Zabbix でデータベースを監視する 3 つの方法
Zabbix でデータベースの値を取る方法は、大きく 3 つです。
| 方法 | どこから DB に接続するか | 向いている用途 |
|---|---|---|
| Zabbix agent 2 のプラグインと公式テンプレート | Agent 2 を入れたホスト | 接続数、スロークエリ、レプリケーションなど DB 自体の状態 |
| ODBC 監視 (Database monitor アイテム) | Zabbix サーバーまたはプロキシ | 自分で書いた SQL の結果 (業務データなど) |
| Agent 2 のカスタムクエリ | Agent 2 を入れたホスト | 自分で書いた SQL を Agent 側で実行したいとき |
DB 自体が元気かどうかを見るなら、まず 1 つ目の公式テンプレートを入れます。テンプレートには、よく使うアイテム (取得する値) とトリガー (障害と判定する条件) が最初からそろっています。業務データを見たいときは 2 つ目か 3 つ目で SQL を足します。
Zabbix agent 2 は Go で書き直された新しいエージェントです。従来の Zabbix agent (C で書かれたもの) と違い、MySQL や PostgreSQL に接続するプラグインを持っています。Agent 2 は DB サーバーに入れてもかまいませんし、別のホストに入れてネットワーク越しに DB へ接続させることもできます。RDS や Cloud SQL のように OS にログインできない DB は、後者の形になります。
MySQL を Zabbix agent 2 で監視する
監視用のユーザーを作る
公式の手順では監視専用のユーザーを作り、必要な権限だけを与えます。
CREATE USER 'zbx_monitor'@'%' IDENTIFIED BY '<password>';
GRANT REPLICATION CLIENT, PROCESS, SHOW DATABASES, SHOW VIEW ON *.* TO 'zbx_monitor'@'%';
'%' はどのホストからでも接続できるという意味です。Agent 2 を動かすホストが決まっているなら、そのアドレスに絞るほうが安全です。MariaDB 10.5.9 以降でレプリケーションの値も取る場合は、SLAVE MONITOR の権限も必要です。MySQL 8.4 以降を監視するときは、Zabbix agent 2 を 7.0.22 以降にするようテンプレートの説明に書かれています。
ホストにテンプレートをリンクする
Zabbix の画面でホストを作り、テンプレート「MySQL by Zabbix agent 2」をリンクします。そのうえで、ホストのマクロ (テンプレートの中で使う変数) に接続情報を設定します。
| マクロ | 設定する値 |
|---|---|
{$MYSQL.DSN} |
接続先。例: tcp://localhost:3306、または Agent 2 の設定ファイルで定義したセッション名 |
{$MYSQL.USER} |
zbx_monitor |
{$MYSQL.PASSWORD} |
作ったユーザーのパスワード |
パスワードを Zabbix の画面に置きたくない場合は、Agent 2 の設定で名前付きセッションを定義し、{$MYSQL.DSN} にはそのセッション名だけを書きます。
Plugins.Mysql.Sessions.prod.Uri=tcp://10.0.1.20:3306
Plugins.Mysql.Sessions.prod.User=zbx_monitor
Plugins.Mysql.Sessions.prod.Password=<password>
パラメータ名の先頭は Plugins.Mysql で、MySQL ではない点に気をつけてください。
設定できたら、「Monitoring → Latest data」(最新データ) の画面で値が入っているかを確かめます。公式の手順では、{$MYSQL.USER} をわざと違う名前にして「MySQL: Service is down」の障害が出ることを確かめ、元に戻す方法が紹介されています。
主なアイテムとトリガー
テンプレートには多くのアイテムがありますが、まず押さえておきたいのは次のトリガーです (Zabbix 7.0 のテンプレートの README より)。
| トリガー | 何を見ているか | 既定の閾値 (マクロ) |
|---|---|---|
| Service is down | mysql.ping が 0 (接続できない) |
なし |
| Service has been restarted | 稼働時間が 10 分未満 | なし |
| Server has aborted connections | 5 分間の異常切断の頻度 | {$MYSQL.ABORTED_CONN.MAX.WARN} = 3 |
| Refused connections | max_connections による接続拒否 |
なし |
| Server has slow queries | 5 分間のスロークエリの頻度 | {$MYSQL.SLOW_QUERIES.MAX.WARN} = 3 |
| Buffer pool utilization is too low | InnoDB のバッファプールの使用率 | {$MYSQL.BUFF_UTIL.MIN.WARN} = 50 (%) |
| Replication lag is too high | レプリケーションの遅れ | {$MYSQL.REPL_LAG.MAX.WARN} = 30m |
「Refused connections」が出たら接続数が上限に達しています。原因の調べ方は Too many connections の原因と対処 で説明しています。「Server has slow queries」は MySQL の Slow_queries (long_query_time を超えたクエリの数) をもとにしているので、どのクエリが遅いかはスロークエリログで調べます。手順は MySQL のスロークエリの見つけ方 にまとめています。
閾値はマクロで変えられます。テンプレートの値をそのまま使うと、自分の環境では鳴りすぎたり鳴らなすぎたりすることがあるので、数週間のデータを見てからホストのマクロで上書きします。閾値の決め方は アラートの閾値の決め方 も参考にしてください。
PostgreSQL を Zabbix agent 2 で監視する
プラグインを入れる
Zabbix 7.0 では、PostgreSQL のプラグインは Agent 2 本体とは別の「ロード可能なプラグイン」です。Zabbix の公式リポジトリからインストールしている場合は、zabbix-agent2-plugin-postgresql のパッケージを追加で入れます。入れ忘れると、テンプレートをリンクしてもアイテムが取得できません。
監視用のユーザーと接続の許可
テンプレートの README の手順では、次のようにユーザーを作り、PostgreSQL に用意されている監視用のロール pg_monitor を与えます。
CREATE USER zbx_monitor WITH PASSWORD '<PASSWORD>' INHERIT;
GRANT pg_monitor TO zbx_monitor;
pg_monitor は、統計情報のビューや設定値を読むための組み込みのロールです。テーブルのデータを書き換える権限は含まれていません。
続いて pg_hba.conf に、このユーザーの接続を許す行を足して、設定を読み込み直します。
host all zbx_monitor 127.0.0.1/32 scram-sha-256
Agent 2 を別のホストで動かすなら、アドレスはそのホストのものにします。
テンプレートとマクロ
ホストにテンプレート「PostgreSQL by Zabbix agent 2」をリンクし、マクロを設定します。
| マクロ | 既定値 | 意味 |
|---|---|---|
{$PG.CONNSTRING.AGENT2} |
tcp://localhost:5432 |
接続先、またはセッション名 |
{$PG.USER} |
zbx_monitor |
監視用ユーザー |
{$PG.PASSWORD} |
(要設定) | パスワード |
{$PG.DATABASE} |
postgres |
最初に接続するデータベース |
主なアイテムとトリガー
| トリガー | 何を見ているか | 既定の閾値 (マクロ) |
|---|---|---|
| Service is down | pgsql.ping が 0 |
なし |
| Total number of connections is too high | 接続数が max_connections に占める割合 (5 分間の最小値) |
{$PG.CONN_TOTAL_PCT.MAX.WARN} = 90 (%) |
| Oldest xid is too big | もっとも古いトランザクション ID の年齢 | 18,000,000 |
| Deadlock occurred | データベースごとのデッドロックの頻度 | {$PG.DEADLOCKS.MAX.WARN} = 0 |
| Too many slow queries | 実行中で時間がかかっているクエリの数 | {$PG.SLOW_QUERIES.MAX.WARN} = 5 |
| Too many recovery conflicts | スタンバイでのリカバリの競合 | {$PG.CONFLICTS.MAX.WARN} = 0 |
「Too many slow queries」で「遅い」とみなす時間は {$PG.QUERY_ETIME.MAX.WARN} (既定 30 秒) です。「Oldest xid is too big」は、VACUUM が追いついていないときに出やすいトリガーです。背景は PostgreSQL の VACUUM で説明しています。デッドロックが出たときの調べ方は デッドロックの原因と対処 を見てください。
このほか、レプリケーションの遅れ (pgsql.replication.lag.sec)、キャッシュのヒット率 (pgsql.cache.hit)、idle in transaction の接続数なども取れます。グラフで推移を見ておくと、障害のときに「いつから変わったか」を追いやすくなります。
ODBC で SQL の結果を監視する
テンプレートの値は DB 自体の状態です。「直近 1 時間の注文数」や「処理待ちのジョブの数」のような業務データは、自分で SQL を書いて取ります。そのとき使いやすいのが ODBC 監視 (Database monitor アイテム) です。
ODBC 監視では、Zabbix サーバー (またはプロキシ) が ODBC ドライバ経由で DB に接続し、SQL を実行します。DB サーバーに何かを入れる必要はありません。公式の ODBC テンプレートとして「MySQL by ODBC」「PostgreSQL by ODBC」もありますが、ここでは業務データのアイテムを自分で作る手順を書きます。
読み取り専用のユーザーを用意する
監視用の SQL を実行するユーザーは、テンプレート用の zbx_monitor とは分け、見たいテーブルの SELECT だけを与えます。PostgreSQL なら次のようにします。
CREATE USER zbx_query WITH PASSWORD '<password>';
GRANT CONNECT ON DATABASE shop TO zbx_query;
GRANT USAGE ON SCHEMA public TO zbx_query;
GRANT SELECT ON orders, payments, jobs TO zbx_query;
MySQL なら GRANT SELECT ON shop.orders TO 'zbx_query'@'<Zabbix サーバーのアドレス>'; のようにテーブルごとに与えます。誤って書き込む SQL を登録しても、権限で止まります。
ドライバと DSN を設定する
Zabbix サーバーに ODBC ドライバを入れます。公式ドキュメントに載っているパッケージ名は次のとおりです。
# Debian / Ubuntu
apt install odbc-postgresql # PostgreSQL
apt install odbc-mariadb # MySQL / MariaDB
# RHEL 系
dnf install postgresql-odbc
dnf install mariadb-connector-odbc
登録されたドライバの名前は odbcinst -q -d で確かめられます。その名前を使って、/etc/odbc.ini にデータソース (DSN) を書きます。
[shopdb]
Description=Shop DB (read only)
Driver=PostgreSQL Unicode
Servername=10.0.1.30
Port=5432
Database=shop
ReadOnly=Yes
SSLmode=require
Driver には odbcinst -q -d で表示された名前を書きます。ユーザー名とパスワードは、ファイルに書かずに Zabbix のアイテムの設定で渡せます。
Zabbix に登録する前に、isql で接続できるかを確かめておくと、問題の切り分けが楽になります。
isql -v shopdb zbx_query '<password>'
「Connected!」と出れば接続できています。もう 1 つ、Zabbix サーバーの設定 StartODBCPollers (ODBC の処理を行うプロセスの数、既定は 1) が 0 になっていないかも確かめます。0 だと Database monitor のアイテムはすべて取得不可 (unsupported) になります。
アイテムを作る
ホストに、タイプ「Database monitor」のアイテムを作ります。キーは次の 3 種類です。
| キー | 返すもの |
|---|---|
db.odbc.select[<説明>,<dsn>] |
1 行目の 1 列目の値 (1 つの値) |
db.odbc.get[<説明>,<dsn>] |
結果全体を JSON の配列で |
db.odbc.discovery[<説明>,<dsn>] |
ローレベルディスカバリ用の JSON |
数値を 1 つ取って推移を見たいなら db.odbc.select が手軽です。たとえば、直近 1 時間の注文数は次のように取ります。
- キー:
db.odbc.select[orders_1h,shopdb] - データ型: 数値 (整数)
- 監視間隔: 5m
- ユーザー名 / パスワード:
zbx_queryとそのパスワード - SQL クエリ:
SELECT count(*)
FROM orders
WHERE created_at >= now() - interval '1 hour';
アイテムの「タイムアウト」は ODBC のログインとクエリ実行のタイムアウトとして使われます。重い集計を短い間隔で回すと本番の DB に負荷がかかるので、条件の列にインデックスがあるかを確かめ、間隔は必要な細かさに合わせます。
トリガーを作る
注文数は時間帯や曜日で大きく変わるので、「10 件を下回ったら」のような固定の閾値は夜中に鳴りやすくなります。Zabbix のトリガー関数には期間をずらす書き方 (タイムシフト) があり、先週の同じ時刻と比べられます。
last(/Shop DB/db.odbc.select[orders_1h,shopdb])
< avg(/Shop DB/db.odbc.select[orders_1h,shopdb],1h:now-1w) * 0.5
and avg(/Shop DB/db.odbc.select[orders_1h,shopdb],1h:now-1w) >= 20
1 つ目の条件は「今の値が、1 週間前の同じ 1 時間の平均の半分を下回った」、2 つ目は「1 週間前のその時間に、比べる意味がある程度の件数があった」です。2 つ目を入れておくと、件数がもともと少ない深夜の小さな揺れで鳴るのを防げます。比べるには、そのアイテムのヒストリを 1 週間分以上残しておく必要があります。
処理待ちのジョブなら、一定時間以上たっても処理されていない件数を数えます。
SELECT count(*)
FROM jobs
WHERE status = 'pending'
AND created_at < now() - interval '15 minutes';
min(/Shop DB/db.odbc.select[stuck_jobs,shopdb],10m) > 0
10 分間ずっと 0 より大きいときだけ障害にするので、一瞬の滞留では鳴りません。
もう 1 つ忘れやすいのが、値が取れなくなったことの検知です。接続できなくなったり SQL がエラーになったりすると、アイテムは取得不可 (unsupported) になり、上のトリガーは評価されなくなります。nodata() で、一定時間データが来ないことを別のトリガーにしておきます。
nodata(/Shop DB/db.odbc.select[orders_1h,shopdb],30m)=1
Agent 2 のカスタムクエリを使う場合
Agent 2 側で SQL を実行したい場合は、カスタムクエリを使います。.sql のファイルをディレクトリに置き、そのディレクトリを設定で指定して、ファイル名をキーに書きます。
# MySQL プラグイン
Plugins.Mysql.CustomQueriesPath=/etc/zabbix/mysql/sql
# PostgreSQL プラグイン
Plugins.PostgreSQL.CustomQueriesPath=/etc/zabbix/postgresql/sql
mysql.custom.query[<接続先>,<ユーザー>,<パスワード>,stuck_jobs]
pgsql.custom.query[<接続先>,<ユーザー>,<パスワード>,<DB 名>,stuck_jobs]
SQL の中では ? をプレースホルダに使い、キーの後ろに引数を並べて値を渡せます (MySQL プラグインの README より)。結果は JSON で返るので、数値として扱うには依存アイテムを作り、前処理の JSONPath で値を取り出します。ODBC のドライバを Zabbix サーバーに入れられない場合や、DB に近いところで実行したい場合に向いています。
業務データを Zabbix で監視するときの限界
ここまでの方法で、業務データもかなりの範囲を Zabbix で見張れます。ただ、運用を続けると次のような手間が出てきます。
まず、何を監視するかを人が決め、SQL を書く必要があります。テーブルの構成を知っている人がいないと始められず、テーブルや列が変わったときに SQL を直すのも人です。
次に、閾値の調整です。タイムシフトで先週と比べても、セール、祝日、月末のように先週と条件が違う日は外れます。閾値を緩めれば見逃しが増え、締めれば誤報が増えます。誤報が続くと通知が読まれなくなります。この問題は アラート疲れの原因と対策 で詳しく扱っています。
最後に、障害が出たあとの調査は人が行います。「注文数が半分になった」という通知だけでは、決済の失敗が増えたのか、特定の商品だけなのか、そもそもアクセスが減ったのかは分かりません。調べるための SQL を、その場で書くことになります。
DB の中身の監視を続けるには
小さく始めるなら、ODBC のアイテムを 2〜3 個だけ作り、注文数とジョブの滞留のように「止まったらすぐ困る数字」から見張るのが現実的です。閾値は 1〜2 週間の値を見てから決め、誤報が出たらそのたびに条件を見直します。Zabbix を使わない場合も、同じ SQL を cron で定期的に実行して結果をチャットに送るだけで、最低限の監視にはなります。業務データの監視全体の考え方は データベース監視とは にまとめています。
SQL や閾値を書く部分を AI に任せる方法もあります。Scandock は、接続文字列を登録すると AI がテーブルの構成と実データを読み、注文数や決済の成否、ジョブの滞留など何を監視するかと、取得と判定の間隔を決めます。固定の閾値ではなく、値の推移や過去の発火の結末を踏まえて異常かどうかを判断し、異常のときは読み取り専用のクエリで関連するデータを調べて、原因・影響・根拠・対処案をつけて通知します。監視と調査は読み取り専用のユーザーで行い、DB サーバーにエージェントを入れる必要はありません。
参考
- Zabbix Life Cycle & Release Policy
- Zabbix 7.0 マニュアル: Zabbix エージェント 2 で MySQL を監視する
- Zabbix 7.0 Manual: Zabbix agent 2 templates
- Zabbix 7.0 Manual: ODBC templates
- MySQL by Zabbix agent 2 (README, release/7.0)
- PostgreSQL by Zabbix agent 2 (README, release/7.0)
- Zabbix 7.0 Manual: ODBC monitoring
- Zabbix 7.0 Manual: Zabbix server (StartODBCPollers)
- Zabbix 7.0 Manual: MySQL plugin
- Zabbix 7.0 Manual: PostgreSQL plugin
- Zabbix 7.0 Manual: Zabbix agent 2 item keys
- Zabbix MySQL plugin README (release/7.0)
- Zabbix 7.0 Manual: Trigger expression