MySQL道普請便り

第251回Group Replicationのマルチプライマリモードにおける外部キーの制限

MySQL 8.0のGroup Replicationは、複数ノード間でトランザクションを複製・認証して整合性を保つことにより、MySQLクラスタを構築するプラグインです。Group Replicationにはシングルプライマリモードとマルチプライマリモードがあり、マルチプライマリモードでは複数のノードから同時に更新が可能かつ書き込みノードをダウンタイムなしで切り替えることができるため、メンテナンス時など運用面でのメリットがあります。その反面、データの一貫性を保つための制約がいくつか存在します。

本記事ではマルチプライマリモードにおける外部キーに関する制約と、運用上の注意点について説明します。

外部キー制約のCASCADEに対する制限

MySQLでは、関連するデータの整合性を保つために外部キー制約が用意されており、ON UPDATE / ON DELETEの参照動作として RESTRICT / NO ACTION / CASCADE / SET NULLなどを指定できます。特にCASCADE系の動作は、親テーブルへの更新・削除が子テーブルへ自動で伝播します。

Group Replicationのマルチプライマリモードでは、外部キーにON DELETE/ON UPDATE CASCADEといったCASCADE動作を定義している場合に制限があります。

MySQLではシステム変数group_replication_enforce_update_everywhere_checks=ONに設定することで、マルチプライマリモードで更新の厳密な整合性チェックを有効にすることができます。この設定により、外部キーが含まれるテーブルに対するCASCADE動作を伴うトランザクションは、グループに同期する段階でコミットが失敗します。

たとえば、親テーブルでDELETEを実行して子テーブルの行を自動削除するようなケースでは、以下のようにエラーが発生してトランザクションがロールバックされます。

ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.

これはクラスタを構成する複数ノードで同時に更新系クエリを実行する場合、CASCADE動作による副次的な削除・更新が同時発生した際に競合を検出できず、データ不整合を招く恐れがあるためです。

また、ON DELETE/UPDATE SET NULLも自動伝播を伴う参照動作であり、マルチプライマリモードでは同様に制限の対象となります。

group_replication_enforce_update_everywhere_checks=OFFに設定していれば、外部キーがあるテーブルに対するCASCADE動作を含むトランザクションはエラーなく実行されますが、MySQL公式としても非推奨であり、データの不整合が発生する可能性はあるため、運用上どうしても必要な場合を除いて使用しないことが推奨されます。もしこの設定を使用する場合は、十分な検証と運用上の制御が必要となります。また、回避策としてはアプリケーション側でCASCADE相当の処理を実装するか、トリガーを使用して明示的に削除・更新を行う方法などが考えられます。

正常なトランザクションがロールバックされるバグ

マルチプライマリモードにおいて外部キーが絡むトランザクションでは、外部キーを持つテーブルに対して並行でINSERTを行うと、競合がない状況でも10~25%程度の高頻度でトランザクションがロールバックされるバグが報告されていますMySQL Bug #96758⁠。このバグが発生した際には以下のエラーが返ります。

ERROR 3101 (40000): Plugin instructed the server to rollback the current transaction.

マルチプライマリモードでは複数のノードから同時に更新が可能ですが、書き込み先を単一ノードに絞っていても発生する可能性がある点には注意が必要です。一方で、シングルプライマリモードでは発生しません。

Group Replicationでは、各トランザクションがどの時点の状態を見て実行されたか(GTID_EXECUTED)と、どの行を変えたか(writeset)を使ってデータの衝突を判定しています。そのためこのバグの原因としては、もし現在のトランザクションより⁠同じか新しい時点の状態⁠⁠同じキー範囲⁠の別の更新処理が先にコミットされていれば、現在のトランザクションは古い状態で実行していると見なされてロールバックされます。

このバグは実質的に仕様上の制約に近く、短期での修正は期待しづらいため、影響を回避するためにはシングルプライマリモードへの切り替えを検討する必要があります。併せて、同一範囲のキーへの並行書き込みを避ける運用とリトライ処理を組み合わせるのが効果的です。

まとめ

Group Replicationのマルチプライマリモードはメリットもあり便利な機能ですが、外部キーを利用する場合には制限があることを認識しておく必要があります。特にMySQLのデフォルト設定ではgroup_replication_enforce_update_everywhere_checks=OFFに設定されているため、CASCADE動作を含むクエリを実行すると気付かないうちにデータの不整合が発生している可能性があるため、注意が必要です。マルチプライマリモードでの外部キー利用においては、アプリケーション側の処理などで適切な対応をして運用することが重要になります。

おすすめ記事

記事・ニュース一覧