MySQL道普請便り

第280回Group Replicationの適用遅延を考慮したメンバー管理

Group Replicationでは、すべてのメンバーがONLINEでも一部のSecondaryだけ更新の適用が遅れることがあります。第274回では状態の確認方法を紹介しましたが、遅延がわかった後はそのメンバーをどう扱うかも考える必要があります。また、第256回で扱ったFlow Controlは、遅いメンバーが追いつけるように書き込み量を調整します。遅延への対処には書き込み量の調整だけでなく、メンバーの扱いを変える方法もあります。

そこで今回は、昇格先の選択に関わるPrimary Electionと、遅延したメンバーの除外に関わるResource Managerを試します。これらのコンポーネントは、MySQL 9.7からCommunity Editionでも利用できるようになりました。

検証環境

今回の検証ではMySQL 9.7.1 Community ServerのDockerコンテナ3台で、Single-Primaryのグループを構成しました。gr1がPrimary、gr2とgr3がSecondaryです。遅延を作るためにgr2の別接続で次のロックを保持し、gr1から更新処理を実行します。

検証用テーブル
CREATE DATABASE lab;
CREATE TABLE lab.slow(id INT PRIMARY KEY, v INT NOT NULL);
INSERT INTO lab.slow VALUES(1, 0);
gr2でロック取得
LOCK TABLES lab.slow READ;
gr1で更新
UPDATE lab.slow SET v=v+1 WHERE id=1;

今回の例では各メンバーのFlow ControlをDISABLEDにして、書き込み制御による影響を除いています。これは少量の更新を使う検証用の設定です。

適用が進んだSecondaryをPrimaryに選ぶ

通常のPrimary自動選出ではMySQLのバージョン、weight、UUIDが使われます。同一バージョンであればweightが大きいメンバーが優先されます。この場合、weightが高くても適用が進んでいるとは限りません。Primary Electionを有効にすると、適用待ちが少ないSecondaryが優先して選択されます。もし最も進んだ候補が複数あればweight、さらにUUIDで決まります。

この機能を有効にするには、全メンバーへのインストールと有効化が必要です。コンポーネントはMySQL 9.7以降であれば同梱されているため、以下のようなクエリでインストールと有効化ができます。

INSTALL COMPONENT
  'file://component_group_replication_elect_prefers_most_updated';
SET GLOBAL group_replication_elect_prefers_most_updated.enabled=ON;

今回はgr2にロックを保持したままgr1で10回更新し、gr1を離脱させて自動選出を確認します。以下のようにweightを異なる値に設定し、weightによらず更新状態によって選択されることを確認します。

gr2
SET GLOBAL group_replication_member_weight=90;
gr3
SET GLOBAL group_replication_member_weight=50;

gr1でSTOP GROUP_REPLICATIONを実行し、Primaryをクラスタから離脱させます。その後クラスタの状態を確認すると、適用が最も進んでいるgr3がPrimaryに昇格していることがわかります。

mysql> SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE
    -> FROM performance_schema.replication_group_members;
+-------------+--------------+-------------+
| MEMBER_HOST | MEMBER_STATE | MEMBER_ROLE |
+-------------+--------------+-------------+
| gr2         | ONLINE       | SECONDARY   |
| gr3         | ONLINE       | PRIMARY     |
+-------------+--------------+-------------+

mysql> SHOW GLOBAL STATUS LIKE 'Gr_latest_primary_election%';
+---------------------------------------------------------------+----------------------------+
| Variable_name                                                 | Value                      |
+---------------------------------------------------------------+----------------------------+
| Gr_latest_primary_election_by_most_uptodate_member_timestamp  | 2026-09-22 11:53:04.484718 |
| Gr_latest_primary_election_by_most_uptodate_members_trx_delta | 10                         |
+---------------------------------------------------------------+----------------------------+

timestampはこの方式でPrimaryが選ばれた時刻です。trx_deltaは選出されたPrimaryと、その次に適用が進んだSecondaryとのトランザクション数の差です。今回はgr2との間に10件の差があったことがわかります。

このようにPrimary Electionでは、weightだけでなく選出時の適用状況を考慮し、適用待ちの少ないSecondaryを新しいPrimaryとして選ぶことができます。

遅延が続くSecondaryを除外する

Resource ManagerはSecondaryのApplier遅延、Recovery遅延、メモリ使用などを監視し、問題が続いたメンバーをグループから外すことができます。ここではApplier遅延を対象にして確認してみます。

このコンポーネントもMySQL 9.7以降であれば同梱されており、以下のようなクエリでインストールできます。

INSTALL COMPONENT 'file://component_group_replication_resource_manager';

デフォルトでは5秒間隔で監視し、10回連続で閾値を超過するとクラスタから除外されます。除外される遅延閾値はデフォルトでは3600秒です。また、再参加直後の再除外を防ぐ猶予期間であるquarantineもデフォルトでは3600秒です。これは再参加後に、離脱中にたまった更新へ追いつくための猶予期間です。

今回は検証用の設定として、gr2の遅延閾値を5秒、猶予期間quarantineも20秒へ変更しています。

gr2の検証用設定
SET GLOBAL group_replication_resource_manager.applier_channel_lag=5;
SET GLOBAL group_replication_resource_manager.quarantine_time=20;

gr1を約5秒間隔で更新し、gr2では除外されるまでロックを保持して検証を行いました。gr1でメンバーを確認すると、以下のようにgr2がクラスタから除外されたことがわかります。

mysql> SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE
    -> FROM performance_schema.replication_group_members;
+-------------+--------------+-------------+
| MEMBER_HOST | MEMBER_STATE | MEMBER_ROLE |
+-------------+--------------+-------------+
| gr1         | ONLINE       | PRIMARY     |
| gr3         | ONLINE       | SECONDARY   |
+-------------+--------------+-------------+

遅延時間、閾値超過サンプル数、除外時刻には専用のステータスがあります。除外のタイミングで対象のgr2で以下のクエリで確認しました。今回の例だと、Applier遅延による除外時刻は11時54分51秒、監視値として遅延58秒と閾値超過11回が記録されています。

mysql> SHOW GLOBAL STATUS WHERE Variable_name IN (
  'Gr_resource_manager_applier_channel_lag',                -- 適用遅延の秒数
  'Gr_resource_manager_applier_channel_threshold_hits',     -- 遅延が閾値を超えたサンプル数
  'Gr_resource_manager_applier_channel_eviction_timestamp'  -- Applier遅延によって最後に除外された時刻
);
+--------------------------------------------------------+----------------------------+
| Variable_name                                          | Value                      |
+--------------------------------------------------------+----------------------------+
| Gr_resource_manager_applier_channel_eviction_timestamp | 2026-09-22 11:54:51.232323 |
| Gr_resource_manager_applier_channel_lag                | 58                         |
| Gr_resource_manager_applier_channel_threshold_hits     | 11                         |
+--------------------------------------------------------+----------------------------+

また、除外理由はgr2のエラーログにも記録されます。以下はメッセージ部分の抜粋です。適用遅延によって除外されたことがわかります。

2026-09-22T11:54:51.232348Z 0 [ERROR] [MY-015569] [Server] Component component_group_replication_resource_manager reported: 'Member exiting group: applier channel lag of 58 seconds exceeded tolerance threshold configured to 5 seconds.'

除外された後は、通常通りgroup_replication_autorejoin_triesなどの設定に従って自動で再参加を試みます。今回の例ではgr2のロックを解放した後、クラスタに再参加したことが確認できました。

まとめ

Primary Electionでは昇格候補の適用状況を考慮し、Resource Managerでは継続的な遅延に応じた除外ができます。しかし、いずれも遅延の原因を解消する機能ではありません。原因の調査を続けながら、昇格先の優先順位やメンバーをどこまで待つかという運用方針に合わせて使うとよいでしょう。

おすすめ記事

記事・ニュース一覧