オープンソースDB運用管理Tips 7

障害発生時でも継続運用を実現する「MySQL」と「PostgreSQL」の「高可用性構成」を理解する

第7回の今回は、障害が発生した場合でも「MySQL」と「PostgreSQL」の運用を継続するための「高可用性構成」について解説します。

梶山 隆輔

6:30

はじめに

この連載では、オープンソースのリレーショナル・データベース(RDB)の「MySQL」と「PostgreSQL」を使いこなすヒントを、両製品の共通点と違いを確認しながら解説していきます。

現在、それぞれの製品をベースとしたクラウド・データベースは複数存在しています。この連載では製品の比較を多く行いますが、製品機能や仕様の優劣についてを論ずる目的のものではないことはあらかじめご了承ください。

第7回の今回は、障害が発生した場合でも「MySQL」と「PostgreSQL」の運用を継続するための「高可用性構成」について解説します。

データベースの可用性とは

データベースは多くのシステムにおいて中心的なコンポーネントです。アプリケーション・サーバーを複数台にしていても、データベースが単一障害点になっていれば、システム全体の可用性、ひいてはビジネスの継続性はそこで制限されます。データベースの高可用性構成では、サーバー障害、プロセス停止、ストレージ障害、ネットワーク障害などに備え、どのように処理を継続するかを設計します。

高可用性には、大きく分けて2つの観点があります。1つは同一データセンター内、または同一リージョン内での障害対策です。これは、1台のサーバーや仮想マシンが停止しても、別のノードに切り替えてサービスを継続するための構成です。

もう1つは、地理的に離れた拠点を使う災害対策です。こちらは、データセンター全体の停止や広域障害に備えるための構成であり、同一拠点内の高可用性構成とは、ネットワーク遅延、RPO (Recovery Point Objective)、RTO (Recovery Time Objective)、切り替え判断などの要件が異なります。

高可用性構成を整理するための観点

データベースの高可用性構成には多くの方式がありますが、まずはいくつかの軸に分けて整理すると理解しやすくなります。

シェアード・エブリシング型とシェアード・ナッシング型

1つ目の分類は、データをどのように保持するかです。

シェアード・エブリシング型は、複数のサーバーが同じストレージやデータ領域を共有する構成です。1台のサーバーに障害が発生した場合、別のサーバーが同じデータ領域を使って処理を引き継ぎます。ストレージを共有するため、データ複製の遅延は問題になりにくい一方、共有ストレージ自体の可用性や、同時アクセス制御が重要になります。

この構成は、多くの場合、データベースが稼働する環境のストレージとクラスタリング・ソフトウェアの機能によって高可用性が実現されます。クラウドでは、Amazon AuroraやOCI Database with PostgreSQLのように分散型かつ共有型のストレージ・アーキテクチャを採用し、ストレージ層で可用性を高めるサービスもあります。

シェアード・ナッシング型は、各ノードがそれぞれ独立したデータ領域を持ち、ノード間でデータを複製する構成です。MySQLやPostgreSQLの高可用性構成では、このシェアード・ナッシング型がよく使われます。本稿でも、MySQLの「InnoDB Cluster」やPostgreSQLの「ストリーミング・レプリケーション」「Pgpool-II」を中心に、シェアード・ナッシング型の構成を見ていきます。

シェアード・ナッシング型の高可用性構成では「ノード間でどのようにデータを複製し、どのタイミングで更新完了とみなすか」が重要になります。また、待機系を通常時にどの状態で動かしておくかによって、切り替え時間や運用コストも変わってきます。

ここでは、「データ複製方式」「同期タイミング」「スタンバイの状態」という3つの観点で整理します。

データ複製方式による分類

シェアード・ナッシング型では、データをどのように複製するかが重要です。代表的な方式として、ログ・シッピング、DBデータ・イメージ転送、ストレージ・データ転送があります。

表1:シェアード・ナッシング型でのデータ複製方式による分類

方式概要代表的な利用例メリット注意点
ログ・シッピング更新内容を記録したログを別ノードへ転送し、受け取った側で再適用する方式MySQLレプリケーション、MySQLグループ・レプリケーション、PostgreSQLのWAL転送/ストリーミング・レプリケーション実装例が多く、差分転送しやすいログ遅延、適用遅延、障害時の未反映データに注意
DBデータ・イメージ転送データベースが管理するデータのまとまりを、DB機能として別ノードへ転送する方式クラスタ参加時の初期同期、再同期、クローン系機能ノード追加や再同期を自動化しやすい転送量が大きくなりやすく、初期同期時の負荷に注意。バージョン間での互換性に制約があることが多い
ストレージ・データ転送ストレージやファイルシステムのレイヤーでデータを複製する方式ストレージレプリケーション、ブロックレベル複製DB製品に依存しにくく、既存インフラを活用しやすいDBとして整合性のある状態を保証する設計が必要

同期型、非同期型、準同期型

次の分類は、更新処理の完了をどのタイミングでクライアントへ返すかです。

表2:更新処理の完了とするタイミングによる分類

方式更新完了の考え方RPOの傾向性能への影響向いている用途
同期型複製先への反映を確認してからクライアントへ完了を返す小さくしやすい。構成によってはゼロを狙える複製先やネットワーク遅延の影響を受けやすい同一DC内の高可用性構成、データ損失を極力避けたいシステム
非同期型プライマリ側で完了した時点でクライアントへ応答し、複製は後から行う障害時に未転送・未適用データを失う可能性がある応答性能への影響は比較的小さい災害対策構成、読み取りレプリカ、性能重視の構成
準同期型少なくとも一部の複製先への到達や受信確認を待ってから応答する非同期より小さくしやすいが、完全同期とは異なる同期型より抑えやすいが、非同期より影響は出やすい可用性と性能のバランスを取りたい構成

アクティブ・アクティブ型とアクティブ・スタンバイ型

高可用性構成は、「通常時に複数ノードをどのように利用するか」という観点でも分類できます。代表的なのが、アクティブ・アクティブ型とアクティブ・スタンバイ型です。

通常時に複数ノードを処理に使う構成をアクティブ・アクティブ型、通常時は主系のみが処理し、待機系が障害時に引き継ぐ構成をアクティブ・スタンバイ型と呼びます。データベースでは、アクティブ・アクティブ型は負荷分散やリソース活用の面で利点がありますが、特に書き込みを複数ノードで受け付ける場合には整合性管理が難しくなります。

ホット・スタンバイ、ウォーム・スタンバイ、コールド・スタンバイ

アクティブ・スタンバイ型はスタンバイ側の利用状態によっても分類できます。

表3:スタンバイ側の利用状態によっても分類

方式スタンバイの状態通常時の利用切り替え時間の傾向注意点
ホット・スタンバイスタンバイが起動済みで、必要に応じて読み取り処理も受け付けられる状態読み取り負荷分散に利用できる場合がある短くしやすい読み取り負荷分散と高可用性を混同しないことが重要
ウォーム・スタンバイスタンバイは待機しているが、通常時は業務処理に使わない、または利用が限定的基本的には待機専用ホットより長く、コールドより短い昇格手順、接続先切り替え、データ追従状況の確認が必要
コールド・スタンバイ通常時は停止、または即時利用できない状態通常時は利用しない長くなりやすい起動、データ同期、復旧作業が必要になり、RTOが長くなりやすい

以降では、これらの分類を踏まえ、MySQLでは「InnoDB Cluster」、PostgreSQLでは「標準のレプリケーション機能」と「Pgpool-II」を中心に見ていきます。

MySQLの高可用性構成

MySQLの高可用性構成では、現在はInnoDB Clusterが標準の選択肢として位置づけられています。InnoDB ClusterはMySQLサーバーとグループ・レプリケーション、MySQL ShellのAdminAPI、MySQL Routerを組み合わせて、MySQLインスタンス群を高可用性クラスタとして構成・管理する仕組みです。

InnoDB Clusterの構成要素

InnoDB Clusterの中心になるのは「グループ・レプリケーション」です。グループ・レプリケーションは複数のMySQLサーバーを1つのグループとして構成し、データを複製しながら高可用性を実現する仕組みです。

InnoDB Clusterでは、クラスタの作成やノード追加、状態確認などをMySQL ShellのAdminAPIで行います。アプリケーションからの接続にはMySQL Routerを利用できます。

MySQL RouterはアプリケーションとMySQLサーバー群の間に配置される軽量ミドルウェアで、バックエンドの適切なMySQLサーバーへトラフィックをルーティングします。

グループ・レプリケーションは、シングル・プライマリ・モードとマルチ・プライマリ・モードのどちらでも動作できます。シングル・プライマリ・モードでは1台のプライマリが書き込みを受け付け、他のメンバーはセカンダリとして動作します。マルチ・プライマリ・モードでは複数ノードが書き込みを受け付けられるアクティブ・アクティブ型となっています。

group_replication_single_primary_modeで指定されるグループ全体の設定によりモードの切り替えが可能で、デフォルトはシングル・プライマリ・モードとされています。シングル・プライマリ・モードでは、障害が発生してプライマリが利用できなくなると、グループ内の別メンバーが新しいプライマリとして選出されます。

マルチ・プライマリ・モードでは、複数のMySQLメンバーが同時に書き込みを受け付けられるため、アクティブ・アクティブ型の構成を取りやすいように見えます。しかし、実際には書き込み競合、DDLとDMLの同時実行、外部キーのカスケード、トランザクション分離レベル、低速メンバーの遅延など、設計上の注意点が多くあります。

特に、グループ・レプリケーションは結果整合性の仕組みであり、すべてのメンバーで常に同じデータが即座に見えるわけではありません。したがって、マルチ・プライマリ・モードは「どのノードにも自由に書き込める構成」と捉えるのではなく、競合が起きにくいワークロードや、書き込み先をアプリケーション側で分離できる構成で採用を検討すべきです。一般的な業務システムでは、シングル・プライマリ・モードのほうがデータ整合性と運用の見通しを立てやすい場面が多いでしょう。

データ同期タイミングと一貫性

グループ・レプリケーションは、旧来型の非同期レプリケーションとは異なり、グループとしてトランザクションの順序や整合性を管理します。ただし、すべてのメンバーで変更が適用されるまで常に待つという単純な同期方式ではありません。そのため、フェイルオーバー直後の読み取りや書き込みでどこまで一貫性を求めるかを設計する必要があります。

MySQLにはgroup_replication_consistencyというシステム変数があり、新しいプライマリが昇格した際に、未適用のトランザクション・ログ(バックログ)がすべて適用されるまで読み取りや書き込みをブロックするかどうかなどを制御できます。この点は、高可用性と性能の関係を考えるうえでも重要です。

一貫性を強める設定にすると、切り替え時や通常時の待ち時間が増える可能性があります。一方で、待ち時間を抑える設定にすれば性能面では有利になりやすいものの、フェイルオーバー直後の見え方には注意が必要です。

フェイルオーバー時に問題になるのは、新プライマリ上でトランザクションが未適用のまま残っている「バックログ」です。ここでは、このバックログ内の未適用トランザクションを「待機対象となる先行トランザクション」としています。

表4:group_replication_consistencyの設定値と一貫性制御の概要

設定値挙動
EVENTUAL読み取り専用トランザクションも読み書きトランザクションも、待機対象となる未適用トランザクションの適用完了を待たずに実行する。性能面の影響は小さい一方、フェイルオーバー直後などに古い値を読む可能性がある
BEFORE_ON_PRIMARY_FAILOVER新しいプライマリに未適用のバックログがある場合、その適用が終わるまで新規の読み取り/書き込みを待機させる。プライマリ切り替え直後の古い読み取りや競合を避けるための設定
BEFOREトランザクション実行前に、先行するトランザクションの適用完了を待機する。読み取り時に最新の値を見たい場合に有効。BEFORE_ON_PRIMARY_FAILOVER の保証も含む
AFTER読み書きトランザクションについて、自分の変更が他のメンバーにも適用されるまで待機する。読み取り専用トランザクションには影響しない。書き込み後に他ノードで読む場合の整合性を強めたいときに使用。BEFORE_ON_PRIMARY_FAILOVER の保証も含む
BEFORE_AND_AFTERBEFOREAFTER の両方を行う。読み書きトランザクションは先行するトランザクションの適用を待ってから実行し、さらに自分の変更が他メンバーに適用されるまで待機する。最も強い一貫性を狙えるが、性能影響も大きくなりやすい設定

EVENTUALは性能寄り、BEFORE_ON_PRIMARY_FAILOVERはフェイルオーバー直後の安全性寄り、BEFOREは読み取り前の同期、AFTERは書き込み後の同期、BEFORE_AND_AFTERはその両方を考慮した設定値になります。

従来型レプリケーションとの違い

MySQLには、2000年にリリースされた3.23.15で実装されたソースとレプリカによる非同期レプリケーションや、MySQL 5.5で加わった準同期レプリケーションがあります。非同期レプリケーションは構成が比較的分かりやすく、読み取り負荷分散やバックアップ取得元としてのレプリカ利用にも適しています。ただし、自動フェイルオーバーやクライアント接続先の切り替えまでを一体で提供するわけではありません。

一方、InnoDB Clusterでは、グループ・レプリケーションによるグループ管理と、MySQL Routerによる接続先のルーティングを組み合わせることで、障害時の切り替えを含めた構成を作りやすくなっています。また、従来型のレプリケーションと比較して、トランザクションの複製をより確実に保証できる点も大きな違いです。

さらに、グループ・レプリケーションと非同期レプリケーションを組み合わせ、MySQL ShellのAdminAPIを使って高可用性と読み取り負荷分散を両立する構成を構築可能です。

MySQL NDB Clusterの位置づけ

MySQLには、InnoDB Clusterとは別に「MySQL NDB Cluster」も存在します。NDB Clusterは、分散コンピューティング環境向けに設計された、アクティブ・アクティブ型の高可用性・高冗長性を持つMySQLの構成です。複数のクラスタを非同期型レプリケーションでつないだ災害対策構成も利用可能です。

データはNDBストレージエンジンのデータノードで管理され、ノード間で複製されており、MySQLサーバーはSQLノードとしてクライアントからのSQLを受け付けます。

NDB Clusterは高い可用性やスケールアウトが求められる用途では有力な選択肢ですが、一般的なInnoDB前提のMySQL構成とは設計思想が大きく異なります。データノードは複数ノードが連動するインメモリ・データベースとして動作し、同期的にデータを複製します。そのため、メモリ、ネットワーク、ノード構成、アプリケーション特性などの要件は厳しくなりやすく、既存のInnoDBベースのシステムをそのまま置き換える構成とは考えないほうがよいでしょう。

PostgreSQLの高可用性構成

PostgreSQLでは、本体に高可用性のための基本機能が用意されています。代表的なのは、WALを利用したログシッピング、ストリーミング・レプリケーション、ホット・スタンバイ、同期レプリケーション、スタンバイの昇格です。

一方で、PostgreSQL本体だけで接続先の自動切り替えやPgpool-IIのようなミドルウェア機能までをすべて提供するわけではありません。そのため、実運用ではPostgreSQL標準機能に加えて、Pgpool-IIのような周辺ツールを組み合わせて高可用性構成を作ることがよくあります。

PostgreSQL標準機能によるレプリケーション

PostgreSQLの高可用性構成の土台になるのは、WALを使ったレプリケーションです。プライマリで発生した変更はWALとして記録され、スタンバイへ転送されます。スタンバイは受け取ったWALを適用することで、プライマリに追従します。

PostgreSQLのドキュメントでは、高可用性、負荷分散、レプリケーションの方式が複数整理されており、同期方式では「データ変更トランザクションがすべてのサーバーでコミットされるまで完了とみなさない」方式、非同期方式では「性能面で有利な一方で障害時にデータ損失の可能性がある」方式として説明されています。

PostgreSQLのスタンバイは、ホット・スタンバイとして読み取り専用の問い合わせを受け付けることができます。これにより、レポート作成や参照系処理をスタンバイへ逃がす構成も可能です。ただし、先に述べた通り、読み取り負荷分散は高可用性そのものではありません。スタンバイへ参照処理を流していても、プライマリ障害時に自動昇格、接続先切り替え、アプリケーションの再接続が適切に行われなければ、高可用性構成としては不十分です。

Pgpool-IIの役割

Pgpool-IIは、PostgreSQLの前段に配置するミドルウェアです。PostgreSQLのMajor Contributor兼コミッタの石井 達夫さんの個人プロジェクトとして始まり、2003年に最初のバージョンが公開されて以来、現在も開発に取り組まれています。

Pgpool-IIを利用するとアプリケーションはPgpool-IIに接続し、Pgpool-IIが背後のPostgreSQLサーバーへ接続を振り分けます。ストリーミング・レプリケーション構成と組み合わせることで、読み取り問い合わせをスタンバイへ振り分けることや、障害検知時にフェイルオーバー処理を実行できます。

Pgpool-IIの設定には複数のクラスタリング・モードがあり、ストリーミング・レプリケーションモード、ロジカル・レプリケーション・モード、ネイティブ・レプリケーション・モード、rawモード、スナップショット・アイソレーション・モードなどがあります。公式ドキュメントでは「いずれのモードでもコネクション・プーリングと自動フェイルオーバーを提供する」と説明されています。

Pgpool-IIとWatchdogによる冗長化

Pgpool-IIを1台だけ配置すると、今度はPgpool-II自体が単一障害点になります。そのため、Pgpool-IIを冗長化するために「Watchdog」を利用します。

Pgpool-IIのドキュメントでは、3台のPgpool-IIを使ってPostgreSQLのプライマリ1台・スタンバイ2台を管理し、単一障害点やスプリットブレインを避ける堅牢なクラスタを運用する構成例が示されています。

この構成では、Pgpool-II同士が互いに監視し、稼働中のPgpool-IIに障害が発生した場合は別のPgpool-IIが処理を引き継ぎます。アプリケーションからは仮想IPなどを使って接続先を固定し、Pgpool-II側でどのPostgreSQLへ接続するかを制御します。

ここでも重要なのは「スプリットブレイン対策」です。PostgreSQLのストリーミング・レプリケーション自体はデータを複製する仕組みです。クラスタ全体としてどのノードをプライマリとみなすか、どのPgpool-IIが仮想IPを持つか、障害時にどの処理を実行するかは、Pgpool-IIやWatchdogのような周辺機能と運用設計で決める必要があります。

MySQLとPostgreSQLの高可用性構成の比較

MySQLとPostgreSQLの高可用性構成は、提供される機能のまとまり方に違いがあります。MySQLではInnoDB Clusterという公式の統合構成があり、グループ・レプリケーション、MySQL Shell、MySQL Routerを組み合わせて高可用性構成を作ります。PostgreSQLでは本体のストリーミング・レプリケーションやホット・スタンバイを土台にしつつ、Pgpool-IIのようなミドルウェアを組み合わせて、接続管理、負荷分散、フェイルオーバー制御を実現します。

表にすると、以下のようになります。

表5:MySQLとPostgreSQLの高可用性構成の比較

観点MySQLPostgreSQL
代表構成InnoDB Clusterストリーミング・レプリケーション + Pgpool-II
中核技術グループ・レプリケーションWAL、ストリーミング・レプリケーション
接続先切り替えMySQL RouterPgpool-II、Watchdog、仮想IPなど
フェイルオーバーInnoDB Clusterの管理機能Pgpool-IIなど周辺ツールとの組み合わせ
読み取り負荷分散Router構成やInnoDB Clusterにレプリカ追加ホット・スタンバイ + Pgpool-II
同期方式グループ・レプリケーション、旧来型非同期レプリケーション、準同期レプリケーション同期/非同期ストリーミング・レプリケーション
スプリットブレイン対策クォーラムWatchdog、仮想IP制御、フェンシング設計
構成の特徴公式統合構成として構築運用しやすい標準機能と周辺ツールを組み合わせて柔軟に設計できる

MySQLのInnoDB Clusterは公式機能として構成要素がまとまっており、導入・管理の流れを一貫して説明しやすい点が特徴です。一方、PostgreSQLは標準機能と周辺ツールを組み合わせる前提のため、構成の自由度が高い反面、どのツールにどの役割を持たせるかを明確にする必要があります。

同一データセンター内の高可用性構成と
広域での災害対策構成の違い

高可用性構成を考える際には、同一データセンター内の高可用性構成(HA)と、地理的に離れた拠点を使う災害対策構成(DR)を分けて考える必要があります。

同一データセンター内の高可用性構成では、サーバー障害や局所的なネットワーク障害に対して、短い時間で別ノードへ切り替えることが目的になります。ネットワーク遅延が小さいため、同期型や準同期型の構成も選択しやすくなります。

一方、災害対策構成では、別リージョンや別データセンター、またはクラウド上にデータを複製し、拠点障害に備えます。距離が離れるほどネットワーク遅延が大きくなるため、完全な同期を前提にするとアプリケーションの応答性能に影響します。そのため、災害対策構成では非同期レプリケーションを採用し、一定のRPOを許容する設計が現実的になることが多くなります。

MySQLでは「InnoDB ClusterSet」が災害対策構成の候補になります。InnoDB ClusterSetは複数のInnoDB Clusterを結び、プライマリ・クラスタとレプリカ・クラスタの構成を取ります。InnoDB ClusterSetのフェイルオーバー機能により、現在のプライマリ・クラスタが動作していない、または接続できない場合に、選択したレプリカ・クラスタを新しいプライマリにできます。また、制御されたスイッチオーバーの手順も用意されています。

PostgreSQLでは、災害対策構成用の単一の公式統合パッケージというより、遠隔地の非同期スタンバイやWALアーカイブ転送を土台にし、必要に応じて接続先切り替えの仕組みを組み合わせる構成になります。

表6:同一データセンター内の高可用性構成と広域での災害対策構成の違い

観点同一データセンター内の高可用性構成広域での災害対策構成
主な目的サーバー障害、プロセス障害、局所的な障害への対応データセンター障害、地域障害、災害への対応
距離低遅延の同一ネットワーク内遠隔地、別リージョン、別拠点
同期方式同期または準同期を選びやすい非同期が中心になりやすい
RPOゼロまたは短めを狙いやすい非同期の場合、一定のデータ損失を許容する設計が必要
RTO短時間切り替えを狙う技術的切り替えに加え、業務判断や接続先変更が絡む
MySQLの例InnoDB ClusterInnoDB ClusterSet
PostgreSQLの例ストリーミング・レプリケーション + Pgpool-II遠隔地の非同期スタンバイ、WALアーカイブ転送

このように、同じ「高可用性」といっても、同一拠点内の障害対策と広域災害対策では、求められる設計が異なります。特に災害対策構成では、切り替えを自動化するか、業務判断を挟むか、DNSや接続先設定をどう変更するか、元の拠点が復旧した後にどう戻すかまで含めて設計する必要があります。

まとめ

今回は、MySQLとPostgreSQLの高可用性構成について、構成方式の分類と代表的な機能を比較しました。MySQLではInnoDB Clusterが中心的な選択肢となり、PostgreSQLでは標準機能であるストリーミング・レプリケーションやホット・スタンバイを土台に、Pgpool-IIを組み合わせて接続管理、負荷分散、フェイルオーバー制御を実現します。

高可用性構成で重要なのは、単にデータを複製することではありません。「障害をどう検知するか」「どのノードを新しいプライマリにするか」「アプリケーションの接続先をどう切り替えるか」「スプリットブレインをどう避けるか」まで含めて設計する必要があります。

また、障害時に自動的に切り替えるフェイルオーバー、メンテナンスなどで計画的に切り替えるスイッチオーバー、障害から復旧した元の環境へ戻すフェイルバックは、それぞれ意味が異なります。特に広域DR構成では、技術的に切り替えられることと、業務として切り替えを判断できることは別問題です。

高可用性構成は「導入して終わり」ではありません。定期的に切り替え訓練を行い、フェイルオーバー後にアプリケーションが正しく動作するか、元の構成へ戻せるか、バックアップや監視と整合しているかを確認することが重要です。

次回は、可用性構成とも密接に関わる監視や運用管理のポイントについて解説していきます。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored