Zabbix DBが遅いとき:MySQLパーティションで解決する実務構築ガイド(第4編)

— 自動パーティションスクリプトとcron管理による完全自動化


概要

本記事では、第3編で作成したパーティション構造を自動的に維持・管理する手順を解説する。
Zabbixはデータ収集量が多いため、毎日・毎月手動でパーティションを追加したり古いデータを削除するのは非効率である。

ここでは次の2つのスクリプトを用いて完全自動化を実現する。

  • /usr/local/bin/zbx-part-history.sh — 日単位(history)パーティションの自動作成+90日前データ削除
  • /usr/local/bin/zbx-part-trends.sh — 月単位(trends)パーティションの自動作成+12か月前データ削除

1) 前提条件

  • 第1〜3編の手順(history/trendsパーティション構成適用)を完了していること
  • MySQL接続アカウント:zabbix
  • /data/history, /data/trends ディレクトリが存在すること
  • UTC基準で動作(cronタイムゾーンはUTCで固定)

2) History 自動化スクリプト

ファイルパス/usr/local/bin/zbx-part-history.sh

#!/usr/bin/env bash
set -euo pipefail

# ===== 基本設定 =====
DB="zabbix"
DB_USER="zabbix"
DB_PASS="ここにDBパスワード"
DB_HOST="127.0.0.1"
TARGET_DIR="/data/history"
DAYS_KEEP=90   # 保持日数

MYSQL() {
  mysql -u"${DB_USER}" -p"${DB_PASS}" -h "${DB_HOST}" --protocol=TCP "${DB}" -Nse "$@" 2>/dev/null
}

# ===== 今日の日付をUTCで計算 =====
TODAY_UTC=$(date -u +%Y-%m-%d)
CURRENT_EPOCH=$(date -u -d "${TODAY_UTC} 00:00:00" +%s)
NEXT_BOUNDARY_EPOCH=$((CURRENT_EPOCH + 86400))   # 翌日00:00
NEXT_TAG=$(date -u -d "@${CURRENT_EPOCH}" +%Y%m%d)

# ===== パーティション存在確認 =====
EXISTS=$(MYSQL "
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='history'
    AND PARTITION_NAME='p${NEXT_TAG}';
")

# ===== 新しいパーティション作成 =====
if [[ "${EXISTS:-0}" -eq 0 ]]; then
  MYSQL "
    ALTER TABLE ${DB}.history
    REORGANIZE PARTITION pMAX INTO (
      PARTITION p${NEXT_TAG}
        VALUES LESS THAN (${NEXT_BOUNDARY_EPOCH})
        DATA DIRECTORY='${TARGET_DIR}',
      PARTITION pMAX VALUES LESS THAN (MAXVALUE)
        DATA DIRECTORY='${TARGET_DIR}'
    );
  "
fi

EXISTS_UINT=$(MYSQL "
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='history_uint'
    AND PARTITION_NAME='p${NEXT_TAG}';
")

if [[ "${EXISTS_UINT:-0}" -eq 0 ]]; then
  MYSQL "
    ALTER TABLE ${DB}.history_uint
    REORGANIZE PARTITION pMAX INTO (
      PARTITION p${NEXT_TAG}
        VALUES LESS THAN (${NEXT_BOUNDARY_EPOCH})
        DATA DIRECTORY='${TARGET_DIR}',
      PARTITION pMAX VALUES LESS THAN (MAXVALUE)
        DATA DIRECTORY='${TARGET_DIR}'
    );
  "
fi

# ===== 古いパーティション自動削除 =====
CUTOFF_EPOCH=$(date -u -d "${DAYS_KEEP} days ago 00:00:00" +%s)

TO_DROP=$(MYSQL "
  SELECT GROUP_CONCAT(PARTITION_NAME)
  FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='history'
    AND PARTITION_NAME REGEXP '^p[0-9]{8}$'
    AND PARTITION_DESCRIPTION < ${CUTOFF_EPOCH};
" || true)

if [[ -n "${TO_DROP:-}" && "${TO_DROP}" != "NULL" ]]; then
  MYSQL "ALTER TABLE ${DB}.history DROP PARTITION ${TO_DROP};"
fi

TO_DROP2=$(MYSQL "
  SELECT GROUP_CONCAT(PARTITION_NAME)
  FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='history_uint'
    AND PARTITION_NAME REGEXP '^p[0-9]{8}$'
    AND PARTITION_DESCRIPTION < ${CUTOFF_EPOCH};
" || true)

if [[ -n "${TO_DROP2:-}" && "${TO_DROP2}" != "NULL" ]]; then
  MYSQL "ALTER TABLE ${DB}.history_uint DROP PARTITION ${TO_DROP2};"
fi

保存後、実行権限を付与:

# chmod +x /usr/local/bin/zbx-part-history.sh

3) Trends 自動化スクリプト

ファイルパス/usr/local/bin/zbx-part-trends.sh

#!/usr/bin/env bash
set -euo pipefail

# ===== 基本設定 =====
DB="zabbix"
DB_USER="zabbix"
DB_PASS="ここにDBパスワード"
DB_HOST="127.0.0.1"
TARGET_DIR="/data/trends"
MONTHS_KEEP=12   # 保持月数

MYSQL() {
  mysql -u"${DB_USER}" -p"${DB_PASS}" -h "${DB_HOST}" --protocol=TCP "${DB}" -Nse "$@"
}

# ===== 月の境界値計算 =====
CURRENT_MONTH=$(date -u +%Y-%m-01)
CURRENT_EPOCH=$(date -u -d "${CURRENT_MONTH}" +%s)
NEXT_MONTH_EPOCH=$(date -u -d "${CURRENT_MONTH} +1 month" +%s)
NEXT_TAG=$(date -u -d "${CURRENT_MONTH}" +%Y%m)

# ===== パーティション存在確認・作成 =====
EXISTS=$(MYSQL "
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='trends'
    AND PARTITION_NAME='p${NEXT_TAG}';
")

if [[ "${EXISTS:-0}" -eq 0 ]]; then
  MYSQL "
    ALTER TABLE ${DB}.trends
    REORGANIZE PARTITION pMAX INTO (
      PARTITION p${NEXT_TAG}
        VALUES LESS THAN (${NEXT_MONTH_EPOCH})
        DATA DIRECTORY='${TARGET_DIR}',
      PARTITION pMAX VALUES LESS THAN (MAXVALUE)
        DATA DIRECTORY='${TARGET_DIR}'
    );
  "
fi

EXISTS_UINT=$(MYSQL "
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='trends_uint'
    AND PARTITION_NAME='p${NEXT_TAG}';
")

if [[ "${EXISTS_UINT:-0}" -eq 0 ]]; then
  MYSQL "
    ALTER TABLE ${DB}.trends_uint
    REORGANIZE PARTITION pMAX INTO (
      PARTITION p${NEXT_TAG}
        VALUES LESS THAN (${NEXT_MONTH_EPOCH})
        DATA DIRECTORY='${TARGET_DIR}',
      PARTITION pMAX VALUES LESS THAN (MAXVALUE)
        DATA DIRECTORY='${TARGET_DIR}'
    );
  "
fi

# ===== 古い月次パーティション削除 =====
CUTOFF_EPOCH=$(date -u -d "${CURRENT_MONTH} -${MONTHS_KEEP} months" +%s)

TO_DROP=$(MYSQL "
  SELECT GROUP_CONCAT(PARTITION_NAME)
  FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='trends'
    AND PARTITION_NAME REGEXP '^p[0-9]{6}$'
    AND PARTITION_DESCRIPTION < ${CUTOFF_EPOCH};
" || true)

if [[ -n "${TO_DROP:-}" && "${TO_DROP}" != "NULL" ]]; then
  MYSQL "ALTER TABLE ${DB}.trends DROP PARTITION ${TO_DROP};"
fi

TO_DROP2=$(MYSQL "
  SELECT GROUP_CONCAT(PARTITION_NAME)
  FROM INFORMATION_SCHEMA.PARTITIONS
  WHERE TABLE_SCHEMA='${DB}' AND TABLE_NAME='trends_uint'
    AND PARTITION_NAME REGEXP '^p[0-9]{6}$'
    AND PARTITION_DESCRIPTION < ${CUTOFF_EPOCH};
" || true)

if [[ -n "${TO_DROP2:-}" && "${TO_DROP2}" != "NULL" ]]; then
  MYSQL "ALTER TABLE ${DB}.trends_uint DROP PARTITION ${TO_DROP2};"
fi

保存後、実行権限を付与:

# chmod +x /usr/local/bin/zbx-part-trends.sh

4) cron 登録

cronファイルを作成:

# cat >/etc/cron.d/zbx-partition <<'CRON'
CRON_TZ=UTC
5 1 * * * root /usr/local/bin/zbx-part-history.sh >/var/log/zbx-part-history.log 2>&1
10 1 1 * * root /usr/local/bin/zbx-part-trends.sh  >/var/log/zbx-part-trends.log  2>&1
CRON

# chmod 644 /etc/cron.d/zbx-partition
# chown root:root /etc/cron.d/zbx-partition

5) 動作結果サマリー

区分実行周期実行権限MySQLアカウント主な動作
zbx-part-history.sh毎日 01:05 (UTC)root (cron)zabbix翌日のパーティション追加+90日前削除
zbx-part-trends.sh毎月1日 01:10 (UTC)root (cron)zabbix翌月のパーティション追加+12か月前削除

ログファイルの場所

/var/log/zbx-part-history.log
/var/log/zbx-part-trends.log

6) チェックポイント

  • /data/history および /data/trends 配下に
    pYYYYMMDD.ibd, pYYYYMM.ibd 形式のファイルが自動生成されているか確認
  • mysql> SHOW CREATE TABLE zabbix.history\G 実行時に新パーティション情報が反映されていることを確認
  • grep CRON /var/log/syslog でスクリプト実行ログを確認

7) 次回予告

第5編では、Zabbix Housekeeperを無効化し、
CacheSizeHistoryCacheSizeTrendCacheSizeStartDBSyncers などのパラメータを調整して
ZabbixサーバーのキャッシュとMySQL I/Oバランスを最適化する最終チューニングを解説する。


🛠 마지막 수정일: 2025.11.04

💡 お困りですか?
Zabbix、Kubernetes、各種オープンソースインフラの構築・運用・最適化・障害解析が必要であれば、いつでもご連絡ください。

📧 メール: jikimy75@gmail.com
💼 サービス: 導入支援 | 性能チューニング | 障害解析コンサルティング