PostgreSQL | SQLite+MySQL経験者向け、30日で習得するPostgreSQL:設計とパフォーマンス - Day23 バックアップ

SQL PostgreSQL
スポンサーリンク

Day23 後半のゴール

「“とりあえず取る”から“事故前提で設計するバックアップ”へ」

前半で、pg_dump の基本と「バックアップ→リストア」の流れは掴めました。
後半では、もう一歩踏み込んで「本番を意識したバックアップ設計」「pg_dump のモードの違い」「リストア時にハマりやすいポイント」「セキュリティ的に絶対に外せない視点」を整理していきます。


pg_dumpの形式を理解する

「SQL形式だけが答えじゃない」

前半では、いちばん分かりやすい「SQL形式(プレーンテキスト)」を扱いました。
しかし、本番運用を考えると、他の形式も知っておく価値があります。

プレーンテキスト形式(-F p)

pg_dump -F p(デフォルト)で出てくる、いわゆる mydb.sql です。
中身は SQL の羅列で、人間が読める・編集できるのが強みです。

小さめのDB、開発環境のコピー、テーブル構造の確認などにはとても便利ですが、
大規模DBではファイルサイズが大きくなり、並列リストアなどの柔軟性に欠けます。

カスタム形式(-F c)

本番でよく使われるのが、-F c のカスタム形式です。

pg_dump -U myuser -d mydb -F c -f mydb.dump

この形式は、人間が直接読むことは想定されていません。
代わりに、pg_restore というツールを使って、
「どのテーブルからリストアするか」「並列でリストアするか」などを柔軟に制御できます。

大事なポイントは、「大きなDBを本気で守るなら、カスタム形式+pg_restore を覚える価値が高い」ということです。
Day23 では名前だけ押さえておいて、「そういうモードがある」と知っておけば十分です。


リストア時にハマりやすいポイント

「“空のDBに流す”以外のパターンを意識する」

前半の例では、「空のDBを作って、そこに流し込む」というシンプルなパターンを扱いました。
しかし、実務ではもう少し複雑なケースが出てきます。

既存DBに上書きしたいケース

例えば、「本番のスナップショットをステージング環境に反映したい」というケース。
すでにステージングDBが存在していて、その中身を丸ごと入れ替えたい、という状況です。

この場合、

既存のテーブル・制約・データが邪魔をして、
CREATE TABLE や INSERT がエラーになることがあります。

よくあるのが、「テーブルがすでに存在する」「シーケンスの値がズレる」といった問題です。

安全なやり方としては、

ステージングDBを一度 DROP して作り直す
あるいは、別名のDBとしてリストアしてから、アプリ側の接続先を切り替える

といった「丸ごと入れ替え」パターンを取ることが多いです。

一部だけリストアしたいケース

「users テーブルだけ本番から持ってきたい」「特定のマスタだけコピーしたい」といったケースもあります。

このときは、pg_dump 側で -t users のようにテーブルを絞ってバックアップを取り、
リストア側では、既存データをどう扱うか(TRUNCATE してから入れるのか、マージするのか)を設計する必要があります。

ここでの重要ポイントは、「リストアは“ただ流せばいい”ではなく、“既存のものとどう付き合わせるか”の設計が必要」ということです。


バックアップ“だけ”では足りないという現実

「“戻せることを確認していないバックアップ”は、まだ半分」

バックアップ運用で一番怖いのは、「取っているつもりだったけど、いざというときに戻せない」パターンです。

例えば、

バックアップファイルが壊れていた
権限不足で一部のオブジェクトが取れていなかった
バージョン違いでリストア時にエラーが出る

などです。

これを避けるために、本番運用では「リストアテスト」がとても重要になります。

定期的に、バックアップから別環境にリストアしてみる。
アプリがそのDBで正常に動くかを確認する。
その過程で出たエラーや警告を潰していく。

これを繰り返すことで、「このバックアップは本当に“戻せる”」という確信が持てます。

セキュリティ・信頼性の観点から言うと、
「バックアップを取っている」ではなく「バックアップから戻せることを確認している」状態を目指すべきです。


バックアップとトランザクション整合性

「“途中の中途半端な状態”を避ける仕組み」

pg_dump は、基本的に「一貫したスナップショット」を取るように動きます。
つまり、「バックアップ中に他のトランザクションが書き込みをしていても、
バックアップファイルの中身は“ある時点の整合した状態”になる」ように設計されています。

これは、MVCC の仕組みを利用して実現されています。
バックアップ開始時点のスナップショットを掴み、その時点で見えるデータだけを順に読み出していくイメージです。

このおかげで、

バックアップ中にアプリが普通に動いていても、
「途中の行だけ新しくて、他は古い」といった中途半端な状態にはなりません。

ただし、長時間かかるバックアップでは、「バックアップ開始後に作られたテーブルやスキーマ変更」は含まれないことがあります。
「いつ時点のスナップショットか」を意識しておくことは大事です。

ここでのポイントは、「pg_dump は“整合した状態”を取るようにできているが、
それでも“いつ時点の状態か”は設計・運用側で把握しておく必要がある」ということです。


セキュリティ目線でのバックアップ設計

「“バックアップ=本番データのコピー”という自覚を持つ」

バックアップは、セキュリティ的には「本番DBと同じくらい危険なもの」です。
むしろ、ファイルとして持ち出しやすいぶん、リスクは高いとも言えます。

意識しておきたいポイントは、少なくとも次のようなものです。

バックアップファイルの保存先
アクセスできる人・プロセスを最小限にする。
権限のない人が簡単にコピーできる場所に置かない。

暗号化
ディスク暗号化や、バックアップファイル自体の暗号化を検討する。
クラウドストレージに置く場合も、暗号化設定を確認する。

ログ・監査
いつ・誰が・どのバックアップを取得したか。
いつ・どこにリストアしたか。
これらを記録しておくと、万一のときに追跡しやすくなる。

「バックアップは“安心材料”であると同時に、“漏えいリスクの塊”でもある」という二面性を、
エンジニアとしてちゃんと意識しておくことが大事です。


例題:本番DBの“最低限マシな”バックアップ設計を言語化する

「完璧じゃなくていい、でも“何も考えてない”は卒業する」

最後に、あなたが「小さめの本番サービス」を任されたと仮定して、
最低限これくらいは決めておきたい、というバックアップ設計を言葉にしてみます。

毎日深夜に、pg_dump(カスタム形式)でDB単位のバックアップを取る。
バックアップファイルは、アプリサーバとは別のストレージに保存する。
直近7日分は毎日、それより前は週次で一定期間残す。
月に1回は、そのバックアップからステージング環境にリストアして、アプリが動くことを確認する。
バックアップ保存先へのアクセス権限は、運用担当者とバックアップジョブ専用ユーザーに限定する。

これだけでも、「何も考えずにとりあえず pg_dump している」状態からは、かなり前進です。
規模が大きくなれば、ここに「WALベースの連続バックアップ」「ポイントインタイムリカバリ」などが加わっていきますが、
Day23 の時点では、「pg_dump を軸に、事故前提で設計する」という感覚が持てれば十分です。


Day23 後半のまとめ

pg_dump にはプレーンテキスト(SQL)だけでなくカスタム形式など複数の出力形式があり、本番レベルでは「カスタム形式+pg_restore」で“どのテーブルをどういう順番・並列度でリストアするか”を制御できるようにしておくと、大規模DBでも現実的なバックアップ/リストア運用が組める。
リストアは「空のDBに流す」だけでなく「既存DBを入れ替える」「一部テーブルだけ戻す」といったパターンがあり、そのたびに既存データや制約との関係を設計する必要があるうえ、「バックアップから実際に戻せるか」を定期的にテストして初めて“本当に使えるバックアップ”になる。
さらに、pg_dump はMVCCを利用して一貫したスナップショットを取るが「いつ時点の状態か」を運用側が把握しておくこと、そしてバックアップファイル自体が本番データのコピーである以上、保存場所・権限・暗号化・監査を本番DBと同じレベルで設計すること――このあたりまで意識できれば、Day23 後半としてはかなり良いところまで来ている。

タイトルとURLをコピーしました