PostgreSQLバックアップ3分クッキング | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

DBを運用して行く中で課題になるのが日々のデータのバックアップですが、DBにPostgreSQLを採用している場合、非常に簡単な方法でバックアップを設定する事が可能です。


PostgreSQLのバックアップ方法は、ググってみればごまんと出てきますがここではシェルスクリプトを書かずにお手軽に出来るバックアップ方法を記載します。



PostgreSQLのバックアップ方法


1. バックアップ用ディレクトリを作成


バックアップファイルを保存するディレクトリを作成します。

これは何処でもよいですが、前提としてPostgreSQL用ユーザー(ここではpostgres)が書き込めるディレクトリにて作成してください。

ここでは、postgresユーザーのホームディレクトリ以下に作成します。


$ pwd /home/postgres
$ mkdir pg_backup


2. バックアップコマンドをcronへの登録


PostgreSQLのバックアップコマンドは、pg_dumpall コマンドを利用します。

PostgreSQLユーザーでcrontabコマンドを利用して、バックアップコマンドを登録します。


$ su - postgres

$ crontab -e

cronに下記のバックアップコマンドを記載します。


0 3 * * * /usr/local/pgsql/bin/pg_dumpall > /home/postgres/pg_backup/pg_backupall.dmp 2>> /home/postgres/pg_backup/pg_backup.log

実行時間、pg_dumpallコマンドのパスなどは、適宜調整。

ただし、実行時間は後述するlogrotateの実行時間より前に定義しておく必要があります。

(logrotateはcron.dailyに登録されており、RedHat系ではAM4:00に実行されるようにセットされています)


個別のDBだけをバックアップしたい場合は、pg_dumpコマンドでも問題ありません。

その場合は、pg_dumpコマンドの後ろにDB名を付けてあげます。


例)

0 3 * * * /usr/local/pgsql/bin/pg_dump testdb > /home/postgres/pg_backup/pg_backup.dmp 2>> /home/postgres/pg_backup/pg_backup.log

3. logrotateを使ってバックアップファイルをローテーション


さて、ここまでで既に日時のバックアップを取得する事は出来ていますが、このままでは前日のバックアップファイルが最新のものに常に上書きされてしまいます。

最新のバックアップファイルだけがあればよいという要件であれば問題ありませんが、数日前のデータに戻したいというような事もあると思いますので、特定期間のバックアップファイルを残せるようにしておきたいと思います。

バックアップファイルのローテーションは、シェルスクリプトを書くのであれば、その中で定義することが可能ですが、ここではシェルスクリプトを書かないという前提なので、ローテーションにlogrotateコマンドを使う事にします。

logrotateコマンドは、その名のとおりログファイルをローテーションする為のコマンドですが、テキストファイルであれば問題なくローテーションで可能です。


まず、rootユーザーでlogratateの設定ファイルが定義されているディレクトリに移動します。


$ su -

$ cd /etc/logrotate.d/

次に、適当なエディタでログファイルローテーション用のファイルを作成し、下記のように記載します。

(ファイル名はお好みで)


/home/postgres/pg_backup/pg_backupall.dmp {
daily
rotate 12
copy
nocopytruncate
compress
notifempty
nomissingok
}

設定した内容としては

・ 毎日ローテーション実行

・ 保存世代数は12

・ 最新のバックアップファイルはコピーしてそのまま保存しておく

・ ローテーションしたファイルは圧縮する

・ バックアップファイルが空の場合は、ローテーションしない

・ 対象ファイルがない場合は、エラー出力


となっています。

logrotateが上手く定義できない場合は、「logrotateでログファイルがローテーションされない事への対処 」も参照してみてください。



これでPostgreSQLの簡単バックアップは完了です。


※ ここで記載したバックアップ方法は、そこまで信頼性はありません。

  理由は、バックアップコマンドの実行とローテーションのロジックが分離されている為です。

  例えば、バックアップが何らかの理由で上手く動作しなくても、logrotateが動作してしまいます。

  これはつまり、logrotateによって既存のバックアップファイルが削除されてしまう可能性があります。

  (ローテーションの世代数を超えた場合など)

  逆もまた同じで、logrotateが上手く動作しなかった場合、バックアップコマンドによって前日のバックアップファイルが

  上書きされる可能性もあります。



バックアップファイルからリストアする方法


上記でPostgreSQLのバックアップを取得しましたが、リストアする場合は下記の方法で対応可能です。


$ psql template1 < pg_backupall.dmp

※ template1は、PostgreSQLの初期化時に作られる標準システムデータベース名です。

  pg_dumpallを使ってバックアップをしたダンプファイルからリストアする場合、その他の存在するDBを指定することも

  できます。


pg_dumpコマンドを使ってリストアする場合は、バックアップを取得したDB名を指定します。


$ psql testdb < pg_backup.dmp

ただし、リストアしたいDB(上記の場合testdb)の状態により、リストア方法を変えた方がよい場合があります。

pg_dumpコマンドは、(吐き出されたファイルの中身を見れば分かりますが)DDL等のSQLが書かれているに過ぎません。

バックアップは、通常ある時間になったら取得するという方法を取るので、バックアップ後にDBに操作を加えた場合、そのまま前回のバックアップデータからバックアップをしてしまうと整合性が取れなくなる可能性があります。


例えば、バックアップ取得後にテーブルを追加した場合、pg_dumpでとられたバックアップファイルでリストアを行うと、その作成したテーブルは残った状態でリストアされます。

これは、バックアップ時点にシステムを復旧したいという要件から、ずれる事になります。

バックアップ時点でのDBに戻したい場合は、一度DBを再作成し、バックアップファイルからリストアするようにします。


例)

$ dropdb testdb

$ createdb testdb

$ psql testdb < pg_backup.dmp