Mysql データベースのバックアップと復元

投稿日: 2009年4月24日 | カテゴリ:『ワードプレス』>メンテナンス

WordPressのmysqlデータベースのバックアップには、専用のプラグインがあることは周知の事実です。このプラグインは、便利な機能を持ち、動作も安定していますが、セキュリティ、メンテナンスの面で問題があります。この欠点を克服する方向でFedoraサーバーにおけるバックアップの方法を構築してみました。

1. プラグインDatabase backupの問題点
  • プラグインDatabase backupは、「定期バックアップ」機能が付いていて、定時にメールでバックアップファイルを添付して指定したメールアドレスに送信してくれます。しかし、メールはインターネットを介してユーザーのPCに送られてくるので、セキュリティ上問題があります。特に、秘密を保持したいファイルを含んでいる場合には特にそうです。
  • サイトを頻繁に変更するユーザーの場合、バックアップは長くても1日に1回行う必要がありますが、この場合、PCのメール・ボックスにバックアップ・ファイルが蓄積されてしまいます。バックアップ・ファイルは、かなり大きなサイズ(例えば1MBとか)になるので、長期間放置しておくと膨大な量が蓄積されてしまいます。したがってある程度の期間をおいて整理する必要があります。そのための配慮と手間がかかります。
  • myspl以外のファイル、例えば、wp-contentディレクトリにアップロードした画像(uploadsディレクトリ)やその他の追加データなどのバックアップはできません。

これらの欠点を克服する方向で、自宅サーバー内に定期的にバックアップを行う方法を考えてみました。

2. バックアップの基本構造
  1. 保存デバイスは、移動可能なUSBハードデスクとします。この設置方法については以下の記事を参照してください。
    Fedoraサーバーで複数のUSBを使用する方法

  2. 1日に1回、バックアップ対象のディレクトリのファイルの更新状況を調べて、更新されていれば、当該ディレクトリのバックアップ(mysqldumpまたはtar.gz形式)を行う。ファイルには、後でその数を調整するためにバックアップ時の日付を識別子として付加しておく。
  3. 1週間に1回、バックアップ・ディレクトリに保存されているファイルの数を調べて、規定の数以上のファイルは古い順から削除する。
3. mysqlの定期的バックアップ

次のようなスクリプトを書いて定期的にバックアップを行います。

#!/bin/sh
#文字コード=UTF-8
#LOGファイル
log=/var/log/wp-backup.log
#Backup元Directory
folder=/var/lib/mysql/user
#Backup先Directory
bk_dir=/media/backup/mysql
#圧縮ファイル名 Prefix
fname=wordpress_backup
#プログラムの開始
ndate=`date "+%Y-%m-%d"`
echo "">>$log
echo "***** Mysql Backup *****">>$log
echo "開始 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
#sqlディレクトリのポストファイルに変更あるか
diff=`find $folder -type f -ctime -1 | grep -c 'wp_posts.*'`
if [ $diff = 0 ] ; then
 echo "変更されたPostファイルはありません。">>$log
 echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
 exit 0
fi
#cd /backup/wordpress
cd $bk_dir > /dev/null 2>&1
if [ $? -ne 0 ]; then
 echo "ディレクトリが違います。">>$log
 echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
 exit 1
fi
mysqldump --opt --host=localhost --user=user_name --password=xxx Database_name | gzip > $fname-$ndate.sql.gz
echo  "Wordpress mysqlファイルをバックアップしました。" >>$log
chmod -R 700 $bk_dir
echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log

4行目:logを記録するファイルのパスを指定します。
6行目:Backup元のディレクトリのパスを指定します。mysqlのデータベースのディレクトリは、/var/lib/mysqlになります(Fedoraサーバーの場合)。
8行目:Backup先のディレクトリのパスを指定します。ここではUSBハードディスクが使用されています。
10行目:Backupファイルのファイル名の接頭語を指定します。この接頭語は、後にファイルの属性を識別するために使用しますので保存ディレクトリとは異なる名前にしてください。
12行目:現在の時刻を取得
13~15行目:logの先頭部分
17行目:バックアップ元のディレクトリ内のポスト保存ファイル(wp_postsで始まるファイル)の属性(更新時刻、ファイル名の変更など)を調査し、1日以内に変更されているファイルの数を変数に格納する。
18~22行目:変更されたファイルが存在しない場合には、その旨logに記述してプログラムを終了する。変更されているファイルが存在すれば($diff > 0)、バックアップ処理に進む。
24行目:バックアップ先ディレクトリに移動
25~29行目:移動が失敗(バックアップ先ハードディスクがマウントされていない、等)したら、終了。
30行目:mysqldumpは、mysqlデータベースをバックアップする専用のコマンドです。–user=user_nameのuser_nameにはバックアップする対象のユーザー名を指定します。–password=xxxのxxx部にはユーザーのパスワードを記入します。Database_nameにはデータベース名を指定します。
32行目:セキュリティ確保のために、バックアップ・ディレクトリのパーミッションをrootのみのアクセスに限定します。

このプログラムを定期的に実行するには、cronに登録します。以下の設定は毎日4時30分にプログラムを実行する設定です。

[root@localhost ~]# crontab -e
30 04 * * * /root/program/mysql_backup.sh

このプログラムが正常に実行されれば、ポストファイルの属性に変更があった場合にだけバックアップが実施されます。しかし、時間が経過するにつれてバックアップファイルの数が増えてきます。次に、このファイルの数を規定の数だけ残して古い順から削除するプログラムを紹介いたします。

#!/bin/sh
#文字コード=UTF-8
log=/var/log/rm_wp-back-file.log
#BK対象ファイル名を一時保存しておくファイル
dummy=/root/temp/mysql.temp
#保留するファイルの数
hold_num=5
echo "">>$log
echo "**** wp-Mysql Expired ****">>$log
echo "開始 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
#mysql_backup
cd /media/backup/mysql > /dev/null 2>&1
if [ $? -ne 0 ]; then
 echo "ディレクトリが違います。">>$log
 echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
 exit 1
fi
#if directory's files number < $rm_num
num=`find /media/backup/mysql -name "wordpress_backup*" | wc -l`
if [ $num -le $hold_num ]; then
 echo "ファイルの数が$hold_num以下です。">>$log
 echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log
 exit 0
fi
#ファイルの数から保存ファイル数を引く
diff=`expr $num - $hold_num`
nn=$diff
#対象ファイル名をソートして$dummyに出力
find /media/backup/mysql -name "wordpress_backup*" | sort > $dummy
#$diff分だけファイルを削除する
while [ $diff -gt 0 ]; do
rm_file=`head -n $diff $dummy | tail -n 1`
rm -f $rm_file
diff=`expr $diff - 1`
done
echo "mysql バックアップファイルを古いものから$nn個削除しました">>$log
echo "終了 (`date '+%Y年%m月%d日 %H時%M分%S秒'`)">>$log

3行目:logファイルのパス
5行目:バックアップファイル名を古い順にソートして保存する一時ファイルのパス
7行目:留保する最新のバックアップ・ファイルの数。
8~10行目:ログの内容
12行目:バックファイル先ディレクトリに移動
13~17行目:移動に失敗したら、その旨をログに出力して強制終了
19行:バックアップ先ディレクトリを検索して該当するファイル(wordpress_backupを接頭語として持つファイル)の数を変数$numに出力する。
20~24行:ファイルの数が規定数以下ならば、終了。
26行目:存在するファイルの数から規定数の差を計算し、変数$diffに格納する。
27行目:差を変数$nnに退避。
29行目:バックアップ・ファイル接頭語で検索し、見付かったファイル名を昇順にソートして一時ファイルに格納する。
31~35行目:一時ファイルの上から$diff番目のファイル名を取得し、このファイルを削除する。この操作を$diff数が0に達するまで繰り返す。この結果、古い順から$diff数だけファイルが削除される。
36~37行目:ログの出力

このプログラムを週に一回実行するようにcronに登録する。以下は、日曜日の4時35分に実行する設定です。

[root@localhost ~]# crontab -e
35 04 * * 0 /root/program/rm_mysql_bk.sh

以上の2つのプログラムを実行すれば、バックアップ・ディレクトリに、時間の経過と共に新しいバックアップファイルが保存され、その数は規定数に制限されます(つまり、保存サイズを常にほぼ一定に保ちます)。

wp-content以下のディレクトリのバックアップの方法については、以下の記事を参照してください。
Fedoraサーバーにおける部分的バックアップの方法

4. データベースの復元

端末での復元
バックアップ・ファイルが/root/testに存在するとします。

[root@localhost ~]# cd test
[root@localhost test]# ls
wordpress_backup-2009-04-20.sql.gz
[root@localhost test]# gunzip wordpress*
[root@localhost test]# ls
wordpress_backup-2009-04-20.sql
[root@localhost test]# mysql --host=localhost --user=user_name --password=xxxxxx database_name <wordpress_backup-2009-04-20.sql
[root@localhost test]#

phpMyAdminを使用して復元

  1. サーバーのphpMyAdminに接続して当該ユーザーあるいはrootでLoginします。
  2. 左側のメニュー・ウィンドウで復元先のデータベースを選択し、右側の操作ウィンドウで上部にある「インポート」タブを選択します。
  3. 「テキストファイルの位置」の「参照」をクリックし、バックアップファイルを選択します。圧縮されたままのファイルを選択してください。
  4. 以下の図のような設定がなされていることを確認して、「実行」ボタンをクリックします。ファイルの大きさにもよりますが1分ほどかかります。
    adm_restore_start
  5. 「インポートは正常終了しました」の画面が表示されれば成功です。
    adm_restore_end
問題点
  • phpMyAdminで復元作業をする際に、バックアップ・ファイルを解凍した*.sqlファイルを「参照」から呼び込んで実行すると以下の図のようなエラーが出ます。この原因はよくわかりませんが、ドキュメントによれば、php.iniのmemory_limit(デフォルト=32M)、post_max_size(=8M)、upload_max_filesize(= 2M)を調節する対応策があるそうです。圧縮ファイルを選択すれば安定した動作が得られるので、あえてこの対策を点検することはしませんでした。必要とされる方は試してみてください。

adm_restore_error

追記](2009年7月25日)
次のように各値を増加させた結果、圧縮ファイルでも解凍ファイル(sql)でもうまくインポートすることができました。

memory_limit = 32M     
post_max_size = 32M
upload_max_filesize = 32M

インポートするファイルが上記の値を超過している場合には、各値を調整してください。特に最後の値が問題になるようです。
変更を反映するためのhttpdの再スタートもお忘れなく。


関連記事



コメントを残す