GA

2023/08/01

gtid_mode=OFFの移行元MySQLからGroupReplicationにマイグレーションするはなし

  • origin側はgtid_mode=OFF, binlog_format=MIXEDでこれを変えてはいけない
  • MySQLはこのケースに限り 8.0.28 以外でも良い
  • メンテナンスには入れられる。ただし、メンテナンスウィンドウ内でMyDumperをかけられるほどデータは小さくない
  • なおGroupReplication ≠ InnoDB Clusterとした。つまりMySQL Shellの支援とMySQL Routerプロセスは使わない
  • シングルプライマリーモード。MySQL Routerは使わないけど到達性の問題は 俺以外の誰か が何とかするものとする(実際、何とかしてくれた)

まずはフツーに空っぽの状態でGroupReplicationを組む。

これはほぼGetting Startedの通りにいった気がする(3か月くらい前なので既にやや記憶が曖昧)

深く考えずにデータを引っこ抜いて、GroupReplicationのPRIMARYノードに入れる。

Non-GTID環境からGTID環境への非同期レプリケーションは8.0.23でサポートされていたので、遠慮なくそれを使う。

GroupReplication側から

CHANGE REPLICATION SOURCE TO source_host = 'origin_replication_source', source_log_file= .., source_log_pos = .., ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTION = local FOR CHANNEL 'migration' ;

本当は(?) gtid_executedをすっきりさせたかったので group_replication_replication_name を割り当てたかったんだけど、それをやろうとするとError 4021で怒られた。

ERROR 4021 (HY000): CHANGE MASTER TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = <UUID> cannot be executed because the UUID value is equal to the group_replication_group_name.

local だと自分(GroupReplication PRIMARY)の server_uuid を割り当ててくれる。まあそのへんのマシンで uuidgen して持ってきても大して変わらない。

ともあれこれでレプリケーションを開始…

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

早速レプリケーション止まった…(´・ω・`)

原因は2つ、HealthCheckに使っていたMEMORYストレージエンジン(GroupReplicationはInnoDBのテーブル以外は更新できない)と、Primary KeyのないInnoDBテーブル(GroupReplicationはPKもしくはPKE.. 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. .. つまり全カラムがNOT NULLかつUNIQUE制約がついているインデックスが無いとエラーで更新を拒否する。

なおこの2つは同じエラーを返すので、実際はエラーになったSQLスレッドのエラーを見てどっちが原因かを判断する。

MySQL error code MY-003098 (ER_BEFORE_DML_VALIDATION_ERROR): The table does not comply with the requirements by an external plugin.

この2つ(Non-InnoDBテーブルをすべてGR側だけでもInnoDB化し、PKが無いテーブルにすべてPKをつける)が終わればようやくレプリケーションが開始できるが、今回は残念ながら新たにPKを足すという選択肢が無かったので

MySQL :: MySQL 8.0 Reference Manual :: 13.1.20.11 Generated Invisible Primary Keys

MySQL 8.0.30とそれ以降のコイツを使わせてもらうことにした。
基本的にはGR側にデータを突っ込む時だけで良いはずだけれど、過渡期(Asyncレプリケーションを組んだままの期間)が長くてorigin側にPKのないテーブルを追加で作られてしまいそうな場合は CHANGE REPLICATION SOURCE TO に一ひねり加える。

CHANGE REPLICATION SOURCE TO .., REQUIRE_TABLE_PRIMARY_KEY_CHECK = GENERATE;

REQUIRE_TABLE_PRIMARY_KEY_CHECK = GENERATEにして初めて、「originではPKが無かったものをレプリケーションの途中で横取りしてGIPKを足す」になる。これを忘れるとPKが無いままGR側にやってきてまた3098の洗礼を食らうので注意。

(なお、過渡期の間にそんなテーブルをCREATEするな、というネゴシエーションがとれるならこれは別に要らない。正直検証はしたけど、その期間にPKなしでCREATE TABLEされたテーブルなどなかった)

で、取り敢えず頭の図の状態には持って行けたが、もうひと悶着あったのでそれは次回にでも。