はじめに
2021 年 3 月 31 日に、MySQL Database Service High Availability がリリースされました。
MySQL Database High Availability uses MySQL Group Replication to provide standby replicas to protect your data and provide business continuity. MySQL Group Replication implements the Paxos algorithm. A highly available DB System is made up of three MySQL instances, a primary, and two secondaries. All data written to the primary instance is also written to the secondaries. In the event of failure of the primary, one of the secondaries is automatically promoted to primary, is set to read-write mode, and resumes availability to client applications with no data loss. This is called a failover. It is also possible to switch manually, and promote a secondary to primary. This is called a switchover.
引用元 : MySQL Database Service with High Availability
DB システムを作成する際に「高可用性」オプションを指定することで、内部的には Group Replication(グループレプリケーション) を利用した 3 台構成の DB システムが、それぞれ別の可用性ドメインあるいはフォルト・ドメインに作成されるようです。
今回はこの MySQL Database Service High Availability を実際に作成してみて、その内容について確認してみたいと思います。
環境の確認
MySQL Database Service High Availability を利用する場合、ナビゲーションメニューの「MySQL -> DBシステム」から「MySQL DBシステムの作成」を選択すると「高可用性」が新たに追加されているので、このオプションを指定して DB システムを作成します。
しばらくすると作成が完了します。
「スタンドアロン」を選択している場合は「高可用性:無効」となっていましたが、今回は有効になっています。そして、今回は可用性ドメインが 1 つしかなかったため、代わりにフォルト・ドメインが使用されていたので「高可用性タイプ」には Multi-FD と記載されているようです。(別々の可用性ドメインに作成されている場合は Multi-AD と記載されます。)
また、内部的には 3 つのインスタンスが存在しているため、「DBシステム構成」ではそれぞれ括弧内に各リソースの合計量が記載されていることがわかります。なお、これらのリソースについては合計分の料金が必要となりますが、グループレプリケーションのデータ通信などに使用される内部ネットワークについては追加料金がかからないようです。(Billing for High Availability)
なお、今回はホスト名を指定していませんが、DB システム作成時に「拡張オプションの表示 -> Networking」を選択して「ホスト名 オプション」を指定しておくことで、エンドポイントの接続に内部 FQDN を利用することも可能です。
スイッチオーバーについて
「他のアクション -> スイッチオーバー」を選択すると、現在のプライマリから別のセカンダリに手動で切り替えることが可能です。これによって、現在のプライマリはセカンダリに降格し、選択したセカンダリがプライマリに昇格します。
実行をおこなうと、5 分程で変更が完了しました。
変更後はエンドポイントのフォルト・ドメインが FAULT-DOMAIN-2 になっており、正常に切り替わっていることがわかります。
このとき、エンドポイントは変更されていないので、クライアント側は同じプライベート IP アドレス(や内部 FQDN)を使用して接続することが可能ですが、切り替わる際に既存の接続は一度閉じられてしまうので注意してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
mysql> SELECT @@global.hostname; +-------------------+ | @@global.hostname | +-------------------+ | axptpnpyqky2mhp4 | +-------------------+ 1 row in set (0.00 sec) (...スイッチオーバー実施...) mysql> SELECT @@global.hostname; ERROR 2013 (HY000): Lost connection to MySQL server during query mysql> SELECT @@global.hostname; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 36 Current database: *** NONE *** +-------------------+ | @@global.hostname | +-------------------+ | tho6qrkxskm2nvxk | +-------------------+ 1 row in set (0.02 sec) |
システム変数について
続いて、「高可用性」と「スタンドアロン」オプションでシステム変数がいくつか異なっていたので、気になった項目を以下に記載しました。なお、今回はどちらもシェイプを MySQL.VM.Standard.E3.1.8GB にしています。余談ですが、現在「スタンドアロン」を選択すると、グループレプリケーション用のプラグインがデフォルトでインストールされるようになったようです。
- group_replication_advertise_recovery_endpoints = 10.0.19.82:7306(デフォルト値:DEFAULT)
グループレプリケーションにおいてDistributed Recovery(分散リカバリー)を実施する際の接続先を指定します。
DEFAULT の場合はインスタンスのホスト名(hostname)とポート(port)を使用してクライアント接続を試みます。MySQL Database Service High Availability では、インスタンスの IP アドレスと 7306 ポートを別途指定しているようです。 -
group_replication_flow_control_applier_threshold = 2000(デフォルト値:25000)
-
group_replication_flow_control_certifier_threshold = 2000(デフォルト値:25000)
グループレプリケーションにおけるFlow Control(フローコントロール)のタイミングを制御します。設定した値以上のトランザクションがキューに溜まることでフローコントロールが実行されます。
デフォルト値では非常に負荷の大きい環境でないとフローコントロールが発生しないため、今回は 2000 に設定されているようです。なお、この値はシェイプによって自動調整がおこなわれ、MySQL.VM.Standard.E3.2.32GB では 4000 に設定されていました。 -
group_replication_group_name = 6a74016e-16cc-4347-8200-05f119371554(デフォルト値:空)
- group_replication_group_seeds = 10.0.19.82:33061,10.0.39.17:33061,10.0.72.10:33061(デフォルト値:空)
-
group_replication_local_address = 10.0.19.82:33061(デフォルト値:空)
グループレプリケーションを構築すると、このシステム変数に名前やメンバーとなるインスタンスの情報が記載されます。group_replication_group_seeds には各インスタンスのプライベート IP アドレスが記載されていますが、直接アクセスすることはできないようになっています。 -
group_replication_message_cache_size = 429496729(約0.4G)(デフォルト値:1073741824(1G))
グループレプリケーションのメンバー間で通信されるメッセージを保持するキャッシュの最大量を指定します。また、障害が発生したインスタンスが復旧した際は、分散リカバリーを実施する前にキャッシュにデータが残っているかを確認して復旧を試みます。
稼働中は最大でこの値までメモリーを消費してしまうので、今回はデフォルト値より低く設定されているようです。なお、この値はシェイプによって自動調整がおこなわれ、MySQL.VM.Standard.E3.2.32GB では 1717986918(1.6G) に設定されていました。 -
group_replication_transaction_size_limit = 85899345(約80M)(デフォルト値:150000000(約150M))
実行できるトランザクションの最大サイズを指定します。グループレプリケーションではネットワーク負荷による障害の誤検知やパフォーマンスの低下を防ぐために、トランザクションサイズをなるべく小さく保つことが推奨されています。
この値はシェイプによって自動調整がおこなわれ、制限についてはリファレンスに記載されています。 -
sql_require_primary_key = ON(デフォルト値:OFF)
新しいテーブルを作成したり既存テーブルを変更する際に、該当テーブルに主キーがないとエラーを返すようになります。
グループレプリケーションを使用する場合、更新する全てのテーブルに主キー(あるいは NULL でないユニークキー)が存在している必要があるため、このシステム変数が有効になっているようです。
また、グルーレプリケーションに関連する内容でユーザー側で設定可能な値は以下の 2 つのみです。
設定の変更方法については以前の記事に記載されているのでこちらをご参照ください。
- group_replication_consistency = BEFORE_ON_PRIMARY_FAILOVER(デフォルト値:EVENTUAL)
グループレプリケーションにおけるトランザクションの整合性タイミングを制御します。
スイッチオーバーや障害発生時のフェイルオーバー直後にデータの整合性を担保したい場合は、デフォルトの BEFORE_ON_PRIMARY_FAILOVER に設定しておくのが性能影響も小さいため最適であるかと思います。
その他の値についても設定できるようですが、現在の MySQL Database Service High Availability はセカンダリへの負荷分散やマルチプライマリモードが利用できないので、厳密に整合性を管理したい場合を除いて設定する必要はあまりなさそうです。 -
sql_require_primary_key = ON(デフォルト値:OFF)
デフォルトでは有効になっていますが、主キーの有無についてはグループレプリケーションプラグインでも更新クエリを実行する際にチェックをおこなっているため、この値を無効にしていても問題ありません。
導入時の要件について
「高可用性」オプションではグループレプリケーションを利用しているので、使用するためにはグループレプリケーションの要件と制限を満たしている必要があります。
特に重要となるのが以下の項目で、全てのテーブルに主キーあるいは NULL でないユニークキーが存在している必要があります。
Primary Keys. Every table that is to be replicated by the group must have a defined primary key, or primary key equivalent where the equivalent is a non-null unique key.
引用元 : 18.9.1 Group Replication Requirements
そのため、MySQL Database Service High Availability を使用する前に、以下の方法で要件を満たしているかをチェックするようにしてください。
1.以下のクエリを実行して、主キーが存在しないテーブルがあるかどうかをチェックします。
1 2 3 4 5 6 7 8 9 10 11 12 |
SELECT tables.table_schema , tables.table_name , tables.engine FROM information_schema.tables LEFT JOIN ( SELECT table_schema , table_name FROM information_schema.statistics GROUP BY table_schema, table_name, index_name HAVING SUM( case when non_unique = 0 and nullable != 'YES' then 1 else 0 end ) = count(*) ) puks ON tables.table_schema = puks.table_schema AND tables.table_name = puks.table_name WHERE puks.table_name IS null AND tables.table_type = 'BASE TABLE' AND tables.table_schema NOT IN ('performance_schema', 'mysql', 'sys', 'information_schema'); |
2.見つかったテーブルに対して、以下のようなクエリを実行します。
1 |
ALTER TABLE table1 ADD id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY INVISIBLE FIRST; |
なお、上記のクエリは MySQL 8.0.23 から実装された Invisible Columns という機能を利用しており、これによってアプリケーション側の動作に影響を与えることなく主キーを追加することが可能です。
まとめ
ここまで、MySQL Database Service High Availability の基本的な内容について確認してきました。
使用する場合は「高可用性」オプションを選択して作成するだけですので、内部的な仕様について理解していなくても透過的に利用することが可能になっています。(料金は約 3 倍必要になります。)
また、グループレプリケーションにおいて全てのテーブルに主キーが必要であることは導入のハードルになっていましたが、Invisible Columns の導入によってアプリケーション側に影響を与えず対応できるようになっています。これによって、MySQL Database Service High Availability への移行もスムーズにおこなうことができそうです。
今後は MySQL Routerやそれにともなうマルチプライマリモード、セカンダリへの参照振り分け処理の実装など、グループレプリケーションを利用した機能が増えていくのではないかと思うと、これからの MySQL Database Service の動向にも目が離せません。