last update: 26 Apr 2009


PostgreSQLと高可用性システム、大規模システム


この記事は技術評論社『WEB+DB PRESS』『WEB+DB PRESS Vol.48』2008年12月刊 に掲載された原稿の草稿を、許可を得て公開しているものです。
また、日本PostgreSQLユーザ会仕組み分科会で発表したWALとPITRの資料pgpool-IIのオンラインリカバリに関する資料がありますので、こちらも参照してください。

1.1 はじめに

本文書では、PostgreSQLが既に十分な性能と機能を兼ね備え、 高可用性システムや大規模システム向けに着実に進化していることを示します。

1.2 高可用性システム、大規模システムとは

はじめに、今後の議論の主題である高可用性システムと大規模システムについてまとめ、 それぞれが必要とする技術要件を明らかにします。

    1.2.1 高可用性システム

    高可用性システム(High Availability System)とは「稼働率の高いシステム」のことです。 稼働率は以下の式で定義されます。
                          MTBF(平均故障間隔)
    稼働率 = -------------------------------------------
               MTBF(平均故障間隔) + MTTR(平均修復間隔)
         

    ここでMTBF(Mean Time Between Failure)は平均故障間隔で機器やシステムが故障するまでの平均時間間隔、 MTTR(Mean Time To Repair)は機器やシステムの平均修復時間です。

    稼働率の定義式から、稼働率を上げるには次の2つの対策を行えばよいことがわかります。

    1. 故障を起こり難くして、MTBFを大きくする
    2. 障害からの復旧時間を短くして、MTTRを小さくする

    「故障を起こり難くする」には、高信頼性の部品や製品を使うのはもちろんですが、 どんなに高い信頼性を誇る部品であっても故障率をゼロにはできないので、 ハードウエアとソフトウエアの両面から可能な限り「多重化」してシステム全体の信頼性を高めることが肝要です。

    「障害からの復旧時間を短くする」には、データの「バックアップ」を完全に行うと共に、 保存されたデータから元のシステムを復元する「リカバリ」をどれだけ迅速に行えるかが鍵となります。 いくらデータが完全でも、復旧に2日、3日と要しては高可用性システムとは呼べないからです。
    また、「多重化」して障害に備える手法も復旧時間を短くするのに有効です。

    さて、ここで「多重化」について少し掘り下げてみましょう。 多重化の分類にも様々な観点がありますが、ここでは予備サーバの稼働状況と復旧の容易さの観点から4つに分類します(図1)。

    図1 多重化の分類

    1. コールドスタンバイ(cold standby)構成
      予備サーバを準備し、障害発生後にOSとDBMSや業務アプリケーションを起動、データ復旧して業務を開始する。 障害修復時間は長くなる。
    2. ウォームスタンバイ(warm standby)構成
      OSを起動した状態の予備サーバを準備し、バックアップデータを逐次保存しながら待つ。 障害発生後にDBMSや業務アプリケーションを起動、業務を開始する。 コールドスタンバイよりは障害修復時間が短いが、多少の業務停止時間がある。
    3. ホットスタンバイ(hot standby)構成
      OSとDBMSや業務アプリケーションを起動した状態の予備サーバを準備し、バックアップデータを逐次保存しながら待つ。 障害発生後、直ちに業務を開始する。障害修復時間は非常に短い。
    4. 負荷分散構成
      常時、複数のサーバを稼働させた状態で処理を分散させる。 障害が発生したサーバを切り離して、正常なサーバのみで稼働(縮退運用)する。
      縮退運用から正常運用に戻すことを「リカバリ」といい、 特にシステムを無停止でリカバリできる場合は「オンラインリカバリ」という。

    ここで「冗長化」と「多重化」について。 冗長化とは部品やサーバなどのシステムコンポーネントを多めに用意しておき、 一部のコンポーネントが故障してもサービスを継続できるようにしておくことです。 よって、冗長化されたシステムは一部が予備として待機していて、稼働していません。
    一方、多重化とは単にシステムコンポーネントを複数用意した構成のことで、 各コンポーネントの稼働状況は関係しません。

    厳密にはコールドスタンバイ構成などの「冗長化」と負荷分散構成の「多重化」を区別しなければなりませんが、 説明が繁雑になるのでここでは「多重化」に統一します。

    1.2.2 大規模システム

    高可用性が数式で厳密に定義されているのに対し、「大規模システム」には明確な定義がありません。 感覚的な定義ですが、ここでは
    (1)大量のデータを保持、操作するシステム、
    もしくは
    (2)大量のアクセスがあるシステム、

    を大規模システムと呼ぶことにしましょう。

    特にRDBMSに注目すると、一般に扱うデータが増えるほどDBMSの負荷は増加します。 数メガバイトのデータのなかから検索する場合と比較して、 数ギガバイトや数テラバイトの場合は文字通り桁違いの負荷がDBMSにかかります。 「大量のデータを保持し操作する」には、高性能なストレージやサーバを使うのはもちろん、OSやDBMSなどのミドルウエアも十分に「高性能」なものを選ぶ必要があります。
    また、たとえ保持しているデータが少なくとも、 毎秒数100、数1000と「大量のアクセスが集中する」場合は、 やはりDBMSやWEBサーバが高負荷状態になるので、 サーバを「多重化」するなどの負荷分散対策が必須となります。

    1.2.3 必須の技術要件

    これまでの説明から高可用性システムと大規模システムに必須の技術要件が3つ抽出されました。
    1. 高性能化
      高性能化による処理能力の向上
    2. バックアップ・リカバリ
      障害からの迅速な復旧
    3. 多重化
      システムの信頼性向上、および負荷分散

    本章ではこれら3つの技術要件に注目し、以降はPostgreSQLに対象を絞って解説を進めていきます。
    はじめに、PostgreSQLの性能向上の歴史を簡単に振り返ります。 次に、バックアップ機能の進化について説明します。 最後に、PostgreSQLの多重化を担うレプリケーションソフトについて解説します。

1.3 PostgreSQLの性能向上の歴史

PostgreSQLの最初のバージョン6.0がリリースされたのが1997年1月、 以降絶え間なく開発が続いています。 現在までの間にバージョン6、7、8の3つのメジャーバージョン系列がリリースされました(表1)(脚注1)。
脚注1 PostgreSQLのバージョンはx.y.zで表し、x.yがメジャーバージョン、zがマイナーバージョンを表します。 例えば、バージョン8.3.4はメジャーバージョンが8.3、マイナーバージョンが4です。

表1 バージョン毎の特徴
バージョン 特徴
6.0、6.1、6.2、6.3、6.4、6.5 基本的な機能のみ実装。副問い合わせやトリガなどをサポート
7.0、7.1、7.2、7.3、7.4 主に機能強化が行われたバージョン。外部キーなどSQLレベルの強化、多版型同時実行制御(MVCC)やWAL(Write-ahead Logging)など
8.0、8.1、8.2、8.3、8.4 高可用性、大規模対応。詳細は(表2)

バージョン7.4までに基本的な機能が充実し、さらに広く普及して多くのフィールドテストを経たことで、PostgreSQLは非常に頑健なRDBMSに育ちました。 これらの成果を受け、バージョン8系列ではバッファマネージャや内部ロック、チェックポイントの改良など、 一般にはわかり難いですが非常に効果的な性能向上のための改良が続けられています(表2)。

表2 バージョン8系列での性能向上に関する主な改良点
バージョン リリース時期 性能に関する改良数 主な改良点
8.0 2005.1 15 テーブルスペース、バックグランドライタ、バッファマネージャの改良、チェックポイントの改良、バキューム処理の改良、インデックスの改良
8.1 2005.11 14 共有バッファ同時アクセスの効率化、バッファマネージャの改良、オプティマイザの改良
8.2 2006.12 19 内部ロックの改良、シーケンシャルスキャンの効率化、バキューム処理効率化
8.3 2008.2 15 HOT(HEAP Only Tuple)、チェックポイント時の負荷分散

    1.3.1 代表的な改良点

    バージョン8系列で行われた代表的な改良点について、簡単に説明します。

    1. CHECKPOINTの改良(バージョン8.0)
      これまでは、CHECKPOINT時にすべてのダーティバッファを一気にディスクに書き出していたので、 周期的な性能低下に見舞われることがありました。 バージョン8.0で定期的にダーティバッファを書き出すサブプロセスが追加され、 これによってCHECKPOINT時のディスクI/Oの集中を避け、性能低下を防ぐことができます。

    2. 共有バッファの同時アクセスの改良(バージョン8.1)
      これまでの共有バッファのアクセスのための排他制御は、粗いロックを元にしていたため、 特にマルチCPUのサーバでは性能が劣化していました。 バージョン8.1で、共有バッファのロック関連を見直してスケーラビリティが向上しました。

    3. 共有バッファアルゴリズムの改良(バージョン8.1)
      共有バッファの管理アルゴリズムが LRU(Least Recently Used)から"ClockSweep"置換ポリシーを使用するように変更されました(脚注2)。
      脚注2
      http://itpro.nikkeibp.co.jp/members/ITPro/oss/20050402/158372/

    4. HOTの導入(バージョン8.3)
      HOT(HEAP Only Tuple)とは主にUPDATE文の実行でディスクへの書き込みを抑える機構です(脚注3)。 ベンチマークではHOTの導入前後で30%性能が向上したとの報告もあります。
      脚注3
      http://itpro.nikkeibp.co.jp/article/COLUMN/20070409/267852/?ST=lin-server&P=2
      http://japan.internet.com/webtech/20080207/11.html

    1.3.2 ベンチマーク

    これら大きな改良や、内部処理の細かな改善が積み重なって、 バージョンが上がる毎に目立った性能向上が続いています。
    特に顕著なのは、SMPサーバやマルチコアサーバなど、多くのCPUを持つサーバ上での性能向上で、 バージョン8.1では8CPUまで、バージョン8.2では16CPUまでスケールすることが確認されています。
    少し古い情報ですが、OSS iPediaで公開されたベンチマーク結果があります。
    http://ossipedia.ipa.go.jp/capacity/EV0612250287/index.php

    このベンチマークが行われた時点ではまだバージョン8.2が正式リリースされておらず、 バージョン8.1にパッチを当てたものを使っていますが、これはほぼバージョン8.2と同じものです。

    iPediaには他のRDBMSのベンチマーク結果もありますが、 それらと比較しても処理性能は遜色がなく、CPU数に関してはよりスケールするとの結果も出ています。

    「PostgreSQLは遅い」といわれ続けていましたが、 現時点でPostgreSQLの処理性能が問題となることはほとんどありません。

1.4 PostgreSQLにおけるバックアップ、リカバリ

バージョン8.0以降、PostgreSQLのバックアップとリカバリ機能は急速に発展しました。

    1.4.1 バージョン7までの状況

    バージョン7.4まではpg_dumpコマンドで全データを一度にバックアップする以外ありませんでした(図2)(脚注4)。 ダンプデータはCSV形式かINSERT文の羅列で、 しかも変更分だけをバックアップする差分バックアップにも対応していないので、 データサイズが大きくなり、大規模システムではとても扱い難かったのです。
    脚注4 MySQLのmysqldumpコマンドと同等の機能です。

    図2 pg_dumpによるフルバックアップの取得

    1.4.2 バージョン8.0でサポートされたアーカイブログ機能

    この問題は、バージョン8.0でアーカイブログ機能がサポートされたことにより解決されました。 アーカイブログ機能とは、簡単に言えばデータ変更を逐次記録してファイルに残す機能です(脚注5)。 変更を記録するファイルをアーカイブログと呼びます。
    脚注5 Oracleのアーカイブログモードとほぼ同じと理解してください。

    アーカイブログによるリカバリの原理を簡単に説明します(図3)。
    図3 アーカイブログとリカバリ

    1. はじめにベースバックアップという、リカバリの基本となるデータを作成する。 具体的には、関数pg_start_backup()とpg_stop_backup()の間に、 ベースディレクトリ以下のファイルを、どこか別の場所に保存する。 これがリカバリの基準となる。
    2. 以降はアーカイブログが周期的に保存されていく。 バージョン8.2からは関数pg_switch_xlog()を実行して、明示的にアーカイブログを保存することも可能。
    3. 保存されたベースバックアップとアーカイブログがあれば、 別のサーバにPostgreSQLの複製をつくることが可能。

    これにより、たとえデータベース自体が破損しても、アーカイブログ(とベースバックアップ)が残っていれば、データベースを復元できます。

    1.4.3 アーカイブログ機能の進化

    PostgreSQLにとって待望のアーカイブログ機能でしたが、 導入直後は残念ながら機能的に満足のいくものではありませんでした。 特に大きな問題は「アーカイブログの生成を制御できない」ことでした。 アーカイブログは事前に定めた時間間隔でしか行われないため、 最悪の場合、直前のアーカイブログ作成から数分間から数10分間のデータ変更が失われることがあったのです。

    この問題はバージョン8.2で解決されました。 pg_switch_xlog()関数が実装され、ユーザがこの関数を実行して最新状態のアーカイブログを生成できるようになりました(脚注6)。

    脚注6 もちろん、データ喪失を完全に防げるわけではありません。 肝心なのは明示的にアーカイブログを生成できることです。 これによって、後述するpgpool-IIのオンラインリカバリ機能も実現しました。

    また、バージョン8.3でウォームスタンバイを実現するためのコマンドpg_standbyがサポートされ、 簡単にウォームスタンバイ構成のシステムを構築できるようになりました。

1.5 PostgreSQLにおける多重化

最後に、PostgreSQLにおける多重化について説明します。

PostgreSQLでどのようなソフトウエアが利用できるか、 システム構成別に(表3)に示します。

表3 PostgreSQLによる多重化構成法
構成 修復時間 PostgreSQLでの構成 備考
コールドスタンバイ 長い pg_dump、pg_dumpall、アーカイブログによるリカバリ _
ウォームスタンバイ 短い pg_standby DRBDによる冗長化
ホットスタンバイ 非常に短い 各種レプリケーションソフト DRBDやheartbeatによる冗長化
負荷分散構成 オンラインリカバリの場合無し 各種レプリケーションソフト _

コールドスタンバイ構成の場合は、旧来のpg_dumpコマンドやpg_dumpallコマンド、 バージョン8以降はアーカイブログによるリカバリで構成することができます。
ウォームスタンバイ構成の場合は、バージョン8.3からpg_standbyというプログラムがPostgreSQL本体に付属しています。
また、最近はDRBDでデータベースクラスタを複製し、 ウォームスタンバイ構成やホットスタンバイ構成をとることも多いようです。

ホットスタンバイ構成と負荷分散構成の場合は、いくつかのレプリケーションソフトが利用できます。 個別のソフトの説明の前に、レプリケーションに関する基本的なことがらをまとめておきましょう。

    1.5.1 レプリケーションとは

    レプリケーション(Replication)とは、複数のDBMS間でデータの複製を持つことです。
    レプリケーションは、次の2つの観点から分類できます。
    • マスター・スレーブ/マルチマスター
      マスターが更新(および検索)、スレーブは検索のみを行う`マスター・スレーブ型'か、 すべてのサーバが更新と検索を自由に行う`マルチマスター型'か(図4)。
      図4 マスタ・スレーブ型とマルチマスター型

    • 同期型/非同期型
      データの複製は同期的に行うのか、非同期か(図5)。 同期型はマスター側の更新が確実にスレーブ側に反映されるまで、マスターの更新完了とならない。
      非同期型はマスター側はスレーブ側の更新状況を考慮しない。 よって、データ検索のタイミングによってはマスターとスレーブのデータが一致しない瞬間もあり得る。
      図5 同期型と非同期型


    これらの分類において、たとえば同期型と非同期型のどちらが優れているかという議論は意味がありません。 すべてはシステム要件次第です。課金関連の場合は多少の性能向上を捨てて同期型を選択しなければならないでしょうし、 さほど厳密な表示が求められないSNSや掲示板などは非同期型が選択される場合がほとんどです。

    1.5.2 PostgreSQLのレプリケーションソフト

    MySQLがかなり早い時期からレプリケーションを正式にサポートしたのとは対照的に、 PostgreSQLは今だにレプリケーションを正式サポートしていませんし、サポートする予定もないようです。
    これはどういうことかというと、PostgreSQLの開発ポリシーとして「RDBMSのコア技術のみを実装し、 レプリケーションなどの関連技術はサブプロジェクトとして実装する」を掲げているからです。
    この開発ポリシーには一長一短があるでしょうが、 少なくともレプリケーションに関しては結果的に成功したと言えるでしょう。 なぜなら、これまで10を超えるシステムが様々な設計ポリシーで開発され、 それらの中で時の試練に耐えて生き残ったのが(表4)の3つのシステムだからです。
    表4 PostgreSQLのレプリケーションソフト
    プロジェクト URL 同期/非同期 マスター・スレーブ/マルチマスター レプリケーションする単位 縮退運転 オンラインリカバリ
    Slony-I http://www.slony.info/ 非同期 マスター・スレーブ テーブル 可能 可能
    pgpool-II http://pgfoundry.org/projects/pgpool/ 同期 マルチマスター DB 可能 バージョン2から可能
    PGCluster http://pgfoundry.org/projects/pgcluster/ 同期 マルチマスター DB 可能 可能

    参考までに、(表5)にこれまでにリリースされて現在は開発が終了したレプリケーションソフトの一覧を示します。

    表5 開発が終了したレプリケーションソフト(オープンソースのみ、商用は省く)
    プロジェクト 同期/非同期 マスター・スレーブ/マルチマスター 単位 備考
    eRServer 非同期 マスター・スレーブ テーブル Slony-Iに技術移植
    Rserv 非同期 マスター・スレーブ テーブル _
    DBMirror 非同期 マスター・スレーブ テーブル _
    pgReplicator 非同期 マスター・スレーブ テーブル _
    Usogres 同期 マスター・スレーブ DB 最初期のソフト。役目を終え、自然消滅
    PostgresForest 同期 マルチマスター DB _
    Postgres-R 同期 マルチマスター DB _

    こうしてみると、今も開発が続くこれらの3つのシステムは互いに強みを持ち、 うまく棲み分けができているようにも見えます。 私見ですが、DBの数と同期・非同期で分類すると、 システム構築において(表6)のような選択が可能でしょう。

    表6 システム構築の指針(私案)
    台数\同期非同期 同期 非同期
    2-3台 pgpool-II Slony-I、Slony-I + pgpool-II
    3台以上 PGCluster Slony-I

    さらに(表3)で示したように、DRBDやheartbeatとの組み合わせで適用範囲がさらにひろがります。

1.6 まとめ

以上、 PostgreSQLが高可用性システムと大規模システムに必要な技術要件を クリアしながら着実に進化している様子を駆け足で説明しました。
PostgreSQLが既に十分な性能と機能を兼ね備えていると感じていただければ幸いです。