構造がおかしくなってるっぽい Zabbix の DB を修復する

先日、Zabbix を 1.8.10 から 2.0.5 へとアップグレードしようと思い立ち作業を始めた。

zabbix のサイトにて公開されている rpm でバイナリをインストールした後、DBへのパッチを当てようと思ったところエラーで停止してしまった。

# /usr/share/doc/zabbix-server-mysql-2.0.5/upgrades/dbpatches/2.0/mysql/upgrade zabbix

しばらく待っていたところ

ERROR 1050 (42S01) at line 171: Table 'globalvars' already exists

こんなエラーで止まってしまった。patch.sql で CREATE TABLE しようとしているのだが対象のDB内にすでにそのテーブルが存在してしまっている。ちょっと構造がおかしくなってるのかな。以前アップデートに失敗したときの残骸かな。この辺をキレイにしてしまおう。DB の構造を 1.8.x の形式にキレイにきっちり合わせよう。どうしたらいいかな。と思っていたらずばりそのものを説明するサイトがあった。

chovan.net » How to repair corrupted Zabbix database

だいたい同じ方法で行けたので記録しておく。

■1 zabbix server を停止する

# service zabbix-server stop

■2 念のため DB のバックアップ

MySQL の場合で、以下DB名は zabbix であるとする。

# mysqldump -uroot -p zabbix > ./zabbix_db_`date +%Y%m%d`.dump

当然だが大きなファイルが生成されるので出力先の空き容量に注意すべし。gzip をパイプで通してあげても良い。WRITE の IO が減るのでストレージによっては出力時間が結構短くなる。

■3 テーブルごとにデータだけバックアップ

以下のようなシェルスクリプトを作り、./script.sh zabbix とする。カレントディレクトリにPIDのフォルダが作成されその中にテーブルごとのデータがダンプされる。

#!/bin/bash
db=$1
if [ "$db" = "" ]; then
    echo "Usage: $0 db_name"
    exit 1
fi
mkdir $$
cd $$
clear
for table in `mysql $db -e 'show tables' | egrep -v 'Tables_in_' `; do
    echo "Dumping $table"
    mysqldump --no-create-db --no-create-info $db $table > $table.sql
done
if [ "$table" = "" ]; then
    echo "No tables found in db: $db"
fi

必要に応じて mysql や mysqldump の行に -uroot -pxxxx などの認証情報を入れると良い。

■4 DBを消して作り直す

まずDBを消す。

# mysql -uroot -p -e 'drop database zabbix;'

そして 1.8.x に付属のSQLでDBの入れ物だけ作る。初期データは必要無い。

# mysql -uroot -p -e 'create database zabbix character set utf8 collate utf8_general_ci;'
# mysql -uroot -p zabbix  < ./zabbix-1.8.10/create/schema/mysql.sql

■5 データを戻す

DBの構造が綺麗になったら、そこにデータだけを戻そう。以下のようなシェルスクリプトを作り、./script.sh zabbix とする。FILES= の行は、先ほどの手順でテーブルごとのダンプデータがあるディレクトリを指すように書き換える。

FILES=/tmp/db/9135/*
db=$1
if [ "$db" = "" ]; then
    echo "Usage: $0 db_name"
    exit 1
fi
for f in $FILES
  do
  echo "Processing $f file..."
  mysql $db < $f
done

先ほどと同じように必要に応じて mysql の行に -uroot -pxxxx などの認証情報を入れると良い。

何行かエラーが出ることがあるだろうが気にしなくて良いはず。エラーの内容をよく見てほしい、本来なら 1.8.x には存在しないはずのテーブルについてのエラーなはずだ。無いはずのデータだ。無視して良い。これで綺麗な構造のデータベースが戻ってきた。思う存分アップグレードできる。

※注意点:全消しのあと全戻し(ほぼ全件INSERT)をするので、バイナリログを記録している環境の場合はバイナリログの肥大化に十分注意すべし。平気でギガ単位で膨れあがる。