バックアップとリストア──転ばぬ先の杖
最終章は運用についてです。
運用でまず重要なのは、バックアップとリストアです。データの死はサービスの死と言っても過言ではありません。PostgreSQLのバックアップとリストアを学んでいきましょう。本節では、はじめにRDBMSのバックアップの種類とリストアの設計をおさらいします。そのあと、PostgreSQLでのバックアップツールや勘どころを紹介します。自分のバックアップのやり方を見なおす機会にご活用ください。
そのあとの節では、運用で役立つレプリケーション、パーティション、バージョンアップ、日本語ドキュメントについて解説します。各節を通して、PostgreSQLを実際に使っていくうえでの勘どころを押さえましょう。
バックアップの種類
バックアップには次の種類があります。
- 論理バックアップ
- SQLをそのまま保存する。無停止かつお手軽に実施できる。バックアップした時点までしか戻せない
- 物理バックアップ
- サーバを止めてデータファイルをコピーする。多くの場合、論理バックアップより高速に実施できる。バックアップした時点までしか戻せない
- オンラインバックアップとPITR(Point In Time Recovery)
- 無停止でデータファイルとWALアーカイブをコピーする。最新状態までの任意の時点に戻せる。運用コストは高くなる
論理バックアップは一般的に、無停止でお手軽な反面、データサイズが大きくなるとバックアップの時間が延び、リストア時間もそれに合わせて長くなります。それに対して物理バックアップは、停止を伴いますが、rsync
などでファイルバックアップすればよく、高速に実行できます。どちらも運用はシンプルですが、リストアはバックアップした時点までしか戻せません。
バックアップした直後から最新状態までの任意の時点に戻すには、バックアップ後からの差分が必要になります。この差分を埋めるために、WALを利用したバックアップと、リストアの手法としてPITRを利用する必要があります。PITRは万能に見えますが、データファイルとWALアーカイブの両方の管理が必要なため運用コストが高くなり、リストアにはエンジニアのスキルが必要になります。
このようにそれぞれ、メリットとデメリットがあります。
リストアの設計
リストアを設計するうえでのポイントは稼働率です。表1のように、稼働率から年間の停止可能時間が決まるわけですから、それによって障害対応する場合のバックアップとリストアの方針も決まります。
表1 稼働率
稼働率 | 年間停止時間 | バックアップとリストアの方針 |
90% | 36.5日間 | 月に複数回のメンテナンス時間を設けることができる。論理バックアップや物理バックアップとリストアで十分に対応できる |
99% | 3.65日間 | オンプレミスなら予備のマシンが必要になる。大規模なデータの場合はリストアの所要時間の把握などが必要になる |
99.9% | 8.7時間 | 法定停電や24時間365日対応などシステム以外の部分にも影響が出る99.99% 52分間バックアップからのリストアだけでは達成が難しいため、コールドスタンバイなど冗長化のしくみが必要になる |
99.999% | 5分間 | レプリケーションを利用した、すぐに切り替えられる予備サーバ(ホットスタンバイ)やDR(Disaster Recovery)などの専用のしくみが必要になる |
99.9999% | 32秒間 | 無停止で運用する専用サーバや、大規模な冗長構成のシステムやハードウェアが必要になり、急激にコストが高くなる |
稼働率を高くするにはオンラインで行えるバックアップは必須ですし、夜間などで定期的に停止できるのであれば物理バックアップは高速でお手軽です。どちらも優越ではなく、バックアップの種類と稼働率を踏まえながら、自分たちに合った計画を組むことが重要です。
自分たちの稼働率を決めて、運用方針を決めれば、次は具体的なバックアップとリストアの手法です。以降では、PostgreSQLのバックアップ手法を見ていきましょう。
pg_dump──オンラインで論理バックアップ
一番スタンダートなのは論理バックアップツールであるpg_dumpです。pg_dumpはPostgreSQLに同梱されており、次の4種類からバックアップファイルの形式を選べます。
- プレーンテキスト形式(SQL)
- カスタムアーカイブ形式(圧縮したバイナリ)
- ディレクトリ形式(表単位で圧縮したバイナリ)
- TAR形式(表単位のバイナリ)
お勧めは、カスタムアーカイブ形式です。カスタムアーカイブ形式は、サイズを圧縮できるうえに、リストアの際に必要なテーブルやスキーマ定義だけを分離できます。必要であればプレーンテキスト形式にも変換できるため、いざという場合はSQL文を手作業で編集できます。
カスタムアーカイブ形式でのバックアップとリストアは次のように実行します。
このようにDBの停止を伴わずコマンド一つでバックアップし、復旧方法もコマンド一つですから、運用はシンプルになります。
pg_basebackup──PITRのためのオンラインバックアップ
pg_basebackupは、pg_dumpと同様にPostgreSQLに同梱されており、PITRでリストアするためのデータファイルをオンラインでバックアップするツールです。PostgreSQL 9.1から提供されました。
pg_basebackupはDBを停止しないため、バックアップ中も更新が発生します。そこで、バックアップ中に発生したWALの更新履歴を取得するために、postgresql.conf
を次のように変更してWALアーカイブモードを有効にしておく必要があります。
wal_levelのデフォルトはreplicaになっており、9.6までのデフォルトのminimalの場合はarchive_modeの設定は無視されます。wal_levelにreplicaが設定されたうえで、archive_modeをonにした場合、アーカイブしたWALを保存するコマンドをarchive_commandに指定する必要があります。上記の例では同じサーバに保存していますが、rsyncなどで別のサーバに保存することもできます。
pg_basebackupで作成したバックアップファイルとアーカイブされたWALの合わせ技で、オンラインで完全にデータをバックアップでき、リストアの際も完全に復旧できるのです。
具体的なバックアップとリストアの方法は、次の手順になります。なお、バックアップはオンラインで行えますが、リストアの際はDBへの接続をなくすためにDBを停止してから行いましょう。
リストア時には、pg_basebackupで取得したバックアップからデータファイルを展開します。そのあと、避難した最新のWALを配置してPostgreSQLを起動すると、WALからバックアップとの差分を取得し、DBを復旧してくれます。
recovery.conf
で指定しているrestore_commandは、前述のarchive_commandで保存したWALアーカイブの保存先から取得するコマンドです。recovery_target_timeには、リカバリで戻したい日時を指定します。recovery_target_timeを指定しなかった場合、WALアーカイブとWALファイルから復元できるところまで復元します。
このようにpg_basebackupと稼働中の差分のWALさえあれば、障害直前まで戻すことができます。これが、PostgreSQLのPITRのしくみです。
pg_rman──PITRを助けてくれるツール
「PITRをしたいけどリストア手順が多くて難しい……」という人にお勧めのツールがpg_rmanです。PostgreSQL 11にも対応しており、ソースコードも公開されています。
pg_rmanはpg_basebackupを使ったバックアップとPITRのリストアを簡略化して実施するためのツールです。pg_rmanを利用して作成したバックアップであれば、次のように簡単に最新の状態に復旧できます。もちろん、PITRのメリットである任意の時間にも対応しています。
バックアップをより詳しく知りたい方へ
チュートリアルの動画「PGCon 2014 Tokyo【D1】PostgreSQL バックアップ入門(佐藤 千佳)」が公開されています。当日の登壇資料も公開されています。
レプリケーション──データベースのリアルタイム複製
PostgreSQLはバージョンアップのたびに進化しています。その中でもRDBMSの重要な機能であるレプリケーションは、力を入れて強化されています。
レプリケーションの役割
レプリケーションは、DBをリアルタイムに複製してデータを同期するしくみです。プライマリからスタンバイにWALをもとにデータを連携して複製します。スタンバイは参照することが可能なため、可用性向上や参照の負荷分散などの目的で利用されます。プライマリに障害が発生した場合は、サービスを存続させるためにフェイルオーバーしてスタンバイをプライマリに切り替えます。
昨今ではクラウドサービスを利用すると、気軽にレプリケーションを利用できます。気軽に使えるため、ちゃんと調べずに使っている人も多く見受けられます。レプリケーションは有能な機能ですが制約も多く、問題が発生したときにトラブルシューティングのハードルは高くなりがちです。そこでレプリケーションについてしっかりと学び、レプリケーションのメリットを使い切りましょう。
PostgreSQLではレプリケーションとして、ストリーミングレプリケーションとロジカルレプリケーションの2つをサポートしています。以降で順に見ていきましょう。
ストリーミングレプリケーション──堅牢な複製
PostgreSQLのレプリケーションとしての主流は、ストリーミングレプリケーションです。
ストリーミングレプリケーションは図1のとおり、更新履歴であるWALを利用してレプリケーションします。PostgreSQLのストリーミングレプリケーションの特徴は、スタンバイはリードオンリーのため、書き込みできません。これにより、プライマリとの差分発生を防ぎ、安心してレプリケーションを運用できます。
ストリーミングレプリケーションは、プライマリとスタンバイでPostgreSQLのマイナーバージョンが違ってもレプリケーションできます。しかし、メジャーバージョンが違うとレプリケーションできません。
ロジカルレプリケーション──自由度の高い複製
PostgreSQLのもう一つのレプリケーションが、ロジカルレプリケーションです。PostgreSQL 10から追加されました。ストリーミングレプリケーションと同様にWALを利用してレプリケーションを行いますが、次の違いがあります。
- PostgreSQLのメジャーバージョン違いでのレプリケーションが行える
- テーブル単位でのレプリケーション
- スタンバイへの書き込み
- スタンバイ側へのインデックスやトリガの設定
- 複数のプライマリから1つのスタンバイへ集約
自由度の高さを活かして、いろいろなシーンで利用できます。たとえばAサービスのDBとBサービスのDBで分かれている課金ログを1つのDBにまとめてから集計したり、強大なDBの一部のテーブルのみを取り出してレプリケーションすることなどができます。ただし、デメリットとして、柔軟だからこそデータが壊れやすいという課題があります。
手堅いストリーミングレプリケーションをメインに利用し、ストリーミングレプリケーションではできないことをロジカルレプリケーションでサポートするなど適切に使い分けることで、設計の幅が広がります。
レプリケーションを利用したスタンバイの構成
PostgreSQLでは図2のとおり、ストリーミングレプリケーションやロジカルレプリケーションを利用していろいろなスタンバイの構成を作ることができます。
カスケードレプリケーションは、スタンバイからさらにレプリケーションをして孫スタンバイを作ることで、プライマリの負荷を減らしながらスタンバイを増やせます。
マルチレプリケーションは、プライマリの負担が増えるものの、直接レプリケーションしているスタンバイの数を増やすことで、ホットスタンバイを複数台用意することなどができます。
パーティション──テーブルの水平分割
レプリケーションと同じく、パーティションはRDBMS にとって重要な機能です。しかし、PostgreSQLはバージョン10になるまでパーティション機能がありませんでした。そのため、トリガとPostgreSQLの機能である継承を使って擬似パーティションを作成していましたが、性能や構築の難易度が高く、ほかのRDBMSよりも劣っているというのが実情でした。
本節では、待望の機能であるパーティションを紹介していきます。
パーティションの役割
パーティションは、図3のように、1つのテーブルを複数に分割する機能です。大規模なデータを1つのテーブルに保存しているケースで有用です。アプリケーションからは1つのテーブルに見えるため、分割されていることを意識する必要はありません。テーブルが分割されることで、1つのパーティションに収まったクエリを処理する場合は全体量が小さくなるため、巨大な1つのテーブルを処理するよりも高速になります。
たとえば月次で集計するユーザーの課金履歴があったとします。サービス開始当初は1つのテーブルでまったく問題がなかったとしても、データ量が増えてくると集計SQLで取り出す処理がどんどん重くなっていきます。このような場合、図4のようにパーティションを利用すると、集計対象のデータが月次で分かれるので不要なデータを検索しません。そのため、集計SQLの性能が劇的に改善します。
パーティションの使い方
続いて、パーティションの実際の使い方です。
魅力いっぱいのPostgreSQLのパーティションを利用するためには、図5のとおり、DDLでテーブルを作成する必要があります。作成したテーブルにINSERTを実行すると、分割したテーブルに自動的に振り分けられていることがわかります。たとえば都道府県名やuser_idなどの任意の条件に合わせて、リストや範囲でパーティションできます。これによって、うまく設計すれば更新や参照の負荷を分散できます。
ハッシュパーティション──バランス良く分割する
PostgreSQL 10で追加されたパーティションは、PostgreSQL 11でさらに進化しています。PostgreSQL 11での目玉はハッシュパーティションです。リストや範囲との違いは、図6のように、分割する条件をハッシュにできます。そのため、INSERTごとにラウンドロビンのように分散されていきます。
これにより、更新が多いテーブルやユニークなIDでの参照が多いテーブルでも負荷を分散できますし、IDで取得するようなケースでも参照が分散される効果が期待できます。これは、ハッシュパーティションがなく、シャーディングで水平分割しがちだったuserテーブルなどで効果的な機能です。
そのほかの改善点
PostgreSQL 11のパーティションは、ほかにも紹介しきれないほど多くの改善があります。以下で主要な変更点のみ列挙します。
- パースツリーの作成などクエリを実行するための前準備処理中でもパーティションをすばやく削除できる
- クエリをエグゼキュータが実行中でもパーティションの削除を許可する
- パーティションのキーがUPDATE文で変更された行は、更新された内容に基づいて、自動的に対象のパーティションに移動させる
- パーティション化されたテーブルに、デフォルトのパーティションを指定する
- パーティションテーブルからの外部キーを許可する・パーティションテーブルに対してINSERT ON CONFLICT文を実行する
- パーティションキーが一意性を保証する場合は、パーティションテーブルの一意制約を許可する
毎年メジャーバージョンアップするPostgreSQLですが、パーティションだけを見ても、このように新バージョンになればなるほど改善されていくことがわかると思います。
PostgreSQLのバージョンアップ
ここまで読んで、最新版のPostgreSQLを使いたくなったのではないでしょうか。本節では、PostgreSQLのバージョンアップに必要は知識を紹介します。
メジャーバージョンアップとマイナーバージョンアップの違い
PostgreSQLのバージョンは、次のポリシーで運用されています。
- メジャーバージョンアップ
- 1年に1回、機能追加や機能改善として行われる。第1章で詳述
- マイナーバージョンアップ
- 基本的には2月、5月、8月、11月の3ヵ月に1回、第二木曜日にバグ対応やセキュリティアップデートとして行われる。致命的な問題があれば例外として随時行われる
この周期でバージョンアップし、サポート期間は最新バージョンから4世代前までの5年となっています。
マイナーバージョンアップはバグ対応やセキュリティアップデートですから、PostgreSQLの仕様は基本的に変更されません。そのためアプリケーションへの影響は小さく、比較的簡単にバージョンアップすることができます。
メジャーバージョンアップには機能追加や変更も含まれます。場合によっては互換性のない仕様変更も含まれるため、アプリケーションの改修が必要になることもあります。
リリースノート
PostgreSQLの公式リリースノートはバージョンアップに有用です。変更点だけでなく、前バージョンからのバージョンアップで必要な情報も記載されています。メジャーバージョンアップだけでなく、マイナーバージョンアップの際も作られます。
マイナーバージョン──積極的に追随しよう
マイナーバージョンは、システムを守るためにも積極的に追随しましょう。
マイナーバージョンアップはyum update
などで簡単に行えますが、PostgreSQLの再起動が必要です。ただし、マイナーバージョンが違ってもストリーミングレプリケーションは行えますので、先にスタンバイをマイナーアップデートし、フェイルオーバーして古いプライマリと新しいスタンバイを切り替えることで停止時間を短くするローリングアップデートという方法もあります。
メジャーバージョンアップ──互換性がないこともある
PostgreSQLはMySQLとは異なり、メジャーバージョンが違うDB間のストリーミングレプリケーションが行えません。また、物理バックアップを反映した場合も、メジャーバージョンが違う場合は起動できません。これは、データ構造やWALなどにメジャーバージョン間の互換性がないことがあるためです。
このように無停止で行うことが難しいメジャーバージョンアップですが、新機能や性能の向上などの大きなメリットがあります。
以降では、メジャーバージョンアップするために必要なノウハウを説明します。
pg_dump──リストアしてバージョンアップ
一番簡単な方法は、pg_dumpしたデータを新しいバージョンのPostgreSQLにリストアする方法です。
この方法は、サービスの停止を伴う場合が多く、新しいサーバも必要になります。データサイズが大きいとメンテナンス時間が長くなるため、採用できないケースもあります。
メリットは、シンプルであることと、旧DBが残るためロールバックしやすいことです。バージョンアップ前の検証として本番データを取得し、検証環境で動作確認する際などの用途でもお勧めの方法です。
メンテナンス時間が取れ、更新をある程度停止できるのであれば、この方法を検討しましょう。
pg_upgrade──そのままバージョンアップ
メンテナンス時間は取れるがデータが大規模のため、pg_dumpからリストアする時間が許容できないケースは多々あります。その場合は、PostgreSQLに同梱されているpg_upgradeを利用します。
PostgreSQL 8.4以降はデータファイルの構造が変更されていないため、pg_upgradeはテーブルやインデックスの再構築をしません。制御ファイルやシステムカタログなどを修正してバージョンアップするため、手順としてもシンプルです。
ただし、バージョンダウンはできないため、事前の検証や手順の確認などは周到に行いましょう。
ロジカルレプリケーションによるローリングアップデート
PostgreSQL 10から11へのバージョンアップであれば、ロジカルレプリケーションを利用してマイナーバージョンアップと同様にローリングアップデートできます。更新されるテーブルのみロジカルレプリケーションし、データが同期されたタイミングでマスタを切り替えてバージョンアップができます。図7のようにローリングアップデードを行うことができれば、サービスの停止を最小限に食い止めることができます。
サービス都合でなかなかメジャーバージョンアップできなかったサービスも、今後はロジカルレプリケーションでバージョンアップしやすくなります。
PostgreSQLの日本語情報源
PostgreSQLの魅力の一つは、日本語の公式マニュアルの存在です。また、企業による日本語レポートや、Slackも充実しています。順に見ていきましょう。
公式マニュアル
今回の記事でもたびたび紹介した日本語マニュアルは、本家PostgreSQLコミュニティの英語公式マニュアルをリリースがあるたびに翻訳しています。
注意点として日本語マニュアルは、新しいメジャーバージョンがリリースされると古いメジャーバージョンのマニュアルはメンテナンス対象外になります。そのため、古いバージョンの最新情報を知りたい場合は、英語版を参照しましょう。
日本語マニュアルは、英語版の公式マニュアルとは別にGitHubで管理されており、それをHTMLにビルドしたものがWebに掲載されています。PDFでも配布しており、Webサイトからダウンロードできます。
翻訳への参加
日本語マニュアルのGitHubのpublicリポジトリは、日本PostgreSQLユーザ会の文書・書籍関連分科会の主導のもと管理されています。
GitHub上でのやりとりは日本語で行われており、誰でも歓迎です。IssueもPull Requestも気軽に出すことができます。誤字脱字を指摘するIssueの発行は、特に気軽にできるコミュニティへの貢献です。
興味がある人は、翻訳に参加してください。その際は@noborusさんがまとめた日本語マニュアルの更新方法についてのQiitaの記事「PostgreSQL日本語マニュアルについて」が参考になります。ぜひ一読しましょう。
企業・団体によるレポート
個人で調べるには限界がありますが、企業や団体の力を借りることで有益なレポートが作られています。その中で特に有名なのが次の3つです。
postgresql-jpのSlack
PostgreSQLの有志が集まったSlackがあります。登録すれば誰でも参加できます。
PostgreSQLのコミッターのような上級者から、初心者までが気軽にコミュニケーションできる場所です。いろんな情報が集まりますし、困ったときに相談する#beginnersチャンネルもありますので、活用してください。みなさんの参加をお待ちしています。
特集のまとめ
本特集ではPostgreSQLについて紹介しました。
PostgreSQLに限らず、RDBMSはシステムの重要な役割を担っています。また、RDBMSは寿命が長いソフトウェアです。そのためRDBMSを知ることは重要ですし、学んだことが陳腐化せず、長期にわたり自分を助けるスキルになります。
その中でもPostgreSQLの魅力は、内部構造からコミュニティまで幅広くあります。開発者としてPostgreSQLの開発に参加するのも、ユーザーとして機能をレビューするのもPostgreSQLの楽しみ方の一つです。本特集がみなさんがPostgreSQLを知り、PostgreSQLをより一層使いこなし、PostgreSQLを楽しむきっかけになれば幸いです。
最後になりましたが、本特集の執筆に際して、レビュアーを快く引き受け、そして多くの指摘をくださった@sawada_masahikoさんに感謝します。
- 特集1
イミュータブルデータモデルで始める
実践データモデリング
業務の複雑さをシンプルに表現!
- 特集2
いまはじめるFlutter
iOS/Android両対応アプリを開発してみよう
- 特集3
作って学ぶWeb3
ブロックチェーン、スマートコントラクト、NFT