カジュアルに匿名トランザクションをGTID環境へレプリケーションしよう
MySQL 8.0.23の機能として以下が実装され、匿名トランザクション(GTIDが記録されていないトランザクション)をGTIDが有効化されたMySQLインスタンスへレプリケーションすることが可能となりました。
17.1.3.6 Replication From a Source Without GTIDs to a Replica With GTIDs
従来では、GTIDレプリケーションを行う場合、ソース・レプリカすべてのインスタンスでGTIDが有効化されている必要がありました。
今回はこの機能を使用して、カジュアルにMySQL8.0(非GTID)からMySQL8.0(GTID)へのレプリケーションを行ってみようと思います。
セットアップ
dbdeployer を使用して以下の通りセットアップしました。
1 2 3 4 |
$ curl -OkL https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.23-linux-glibc2.17-x86_64-minimal.tar.xz $ dbdeployer unpack mysql-8.0.23-linux-glibc2.17-x86_64-minimal.tar.xz $ dbdeployer deploy single --sandbox-directory=source-8023 -c server_id=101 8.0.23 $ dbdeployer deploy single --sandbox-directory=replica-8023 --gtid -c server_id=102 8.0.23 |
以下の通りGTIDが有効なインスタンスと従来型のポジションベースで動作するインスタンスを準備しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ dbdeployer global use --version=8.0.23 "select @@port, @@gtid_mode, @@server_id, @@server_uuid, @@gtid_executedG" # Running "use" on replica-8023 *************************** 1. row *************************** @@port: 8024 @@gtid_mode: ON @@server_id: 102 @@server_uuid: 00008024-0000-0000-0000-000000008024 @@gtid_executed: 00008024-0000-0000-0000-000000008024:1-33 # Running "use" on source-8023 *************************** 1. row *************************** @@port: 8023 @@gtid_mode: OFF @@server_id: 101 @@server_uuid: 00008023-0000-0000-0000-000000008023 @@gtid_executed: |
この状態でreplica-8023にレプリケーションソースを設定し、START REPLICAを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ ~/sandboxes/replica-8023/use -e " CHANGE REPLICATION SOURCE TO SOURCE_HOST = '127.0.0.1' , SOURCE_USER = 'msandbox' , SOURCE_PASSWORD = 'msandbox' , SOURCE_PORT = 8023 , MASTER_AUTO_POSITION = 1 " $ ~/sandboxes/replica-8023/use -e "start replica" $ ~/sandboxes/replica-8023/use -e "show replica statusG" | grep Error Last_Error: Last_IO_Error: The replication receiver thread cannot start because the master has GTID_MODE = OFF and this server has GTID_MODE = ON. Last_SQL_Error: Last_IO_Error_Timestamp: 210301 16:33:40 Last_SQL_Error_Timestamp: |
はい。ソースインスタンスではGTIDが有効でないためエラーが出ることが確認できました。
設定を一旦クリアします。
1 |
$ ~/sandboxes/replica-8023/use -e "stop replica; reset replica all;" |
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS を有効化する
非GTID環境からGTID環境へのレプリケーションはレプリケートされてきたトランザクションに、擬似的なGTIDをレプリカ側で割り振る事によって実現します。
From MySQL 8.0.23, you can set up replication channels to assign a GTID to replicated transactions that do not already have one.
This feature enables replication from a source server that does not have GTIDs enabled and does not use GTID-based replication,
to a replica that has GTIDs enabled. If it is possible to enable GTIDs on the replication source server,
as described in Section 17.1.4, “Changing GTID Mode on Online Servers”,
use that approach instead. This feature is designed for replication source servers where you cannot enable GTIDs.
擬似的なGTIDは、CHANGE REPLICATION SOURCE TO の ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS で有効化します。
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS では、疑似的なGTIDをどのように割り振るか指定します。
指定可能な値である、LOCALと[uuid] の2パターン試してみました。
なお、基本的にはレプリケーション自体はGTIDベースではありませんので、SOURCE_AUTO_POSITION を使用することはできません。
ですので、古き良き SOURCE_LOG_FILE
と SOURCE_LOG_POS
で開始ポジションを指定します。
今回はソースインスタンスの静止点が取れるためコマンドで最新のポジションとバイナリログファイルを確認しますが、mysqldumpでレプリカを作成する場合は–master-dataで出力した内容から確認するなどご対応ください。
1 2 3 4 5 6 |
$ ~/sandboxes/source-8023/use -e "show master status" +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000001 | 8330 | | | | +---------------+----------+--------------+------------------+-------------------+ |
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = LOCAL
LOCALを指定すると、レプリカのGTIDとして処理します。
上記をレプリカに設定し、レプリケーションを開始します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ ~/sandboxes/replica-8023/use -e " CHANGE REPLICATION SOURCE TO SOURCE_HOST = '127.0.0.1' , SOURCE_USER = 'msandbox' , SOURCE_PASSWORD = 'msandbox' , SOURCE_PORT = 8023 , SOURCE_LOG_POS= 8330 , SOURCE_LOG_FILE= 'binlog.000001' , ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = LOCAL " $ ~/sandboxes/replica-8023/use -e "start replica" $ ~/sandboxes/replica-8023/use -e "show replica statusG" *************************** 1. row *************************** Replica_IO_State: Waiting for master to send event Source_Host: 127.0.0.1 Source_User: msandbox Source_Port: 8023 Connect_Retry: 60 Source_Log_File: binlog.000001 Read_Source_Log_Pos: 8330 Relay_Log_File: mysql-relay.000002 Relay_Log_Pos: 321 Relay_Source_Log_File: binlog.000001 Replica_IO_Running: Yes Replica_SQL_Running: Yes : Exec_Source_Log_Pos: 8330 : Source_Server_Id: 101 Source_UUID: 00008023-0000-0000-0000-000000008023 Source_Info_File: mysql.slave_master_info : Replica_SQL_Running_State: Slave has read all relay log; waiting for more updates Executed_Gtid_Set: 00008024-0000-0000-0000-000000008024:1-33 Auto_Position: 0 |
ソースインスタンスにworld databaseのデータをインポートし、GTIDを確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ curl -sSkL https://downloads.mysql.com/docs/world.sql.gz | gzip -d -c | ~/sandboxes/source-8023/use $ ~/sandboxes/replica-8023/use -e "select @@gtid_executed" +-------------------------------------------+ | @@gtid_executed | +-------------------------------------------+ | 00008024-0000-0000-0000-000000008024:1-44 | +-------------------------------------------+ $ ~/sandboxes/replica-8023/use -e "show binlog events" | grep Gtid | grep 101 mysql-bin.000001 8327 Gtid 101 8411 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:34' mysql-bin.000001 8532 Gtid 101 8616 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:35' mysql-bin.000001 8759 Gtid 101 8843 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:36' mysql-bin.000001 8975 Gtid 101 9061 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:37' mysql-bin.000001 9560 Gtid 101 9647 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:38' mysql-bin.000001 555411 Gtid 101 555495 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:39' mysql-bin.000001 555630 Gtid 101 555716 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:40' mysql-bin.000001 556591 Gtid 101 556677 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:41' mysql-bin.000001 614469 Gtid 101 614553 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:42' mysql-bin.000001 614696 Gtid 101 614782 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:43' mysql-bin.000001 615310 Gtid 101 615397 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:44' |
想定通り、ソースインスタンスからレプリケートされたトランザクションが、レプリカのGTIDとして 記録されていました。
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = [uuid]
指定したUUIDを使用してGTIDを割り振ることも可能です。
この場合、LOCALとは異なりレプリカインスタンスでの更新によるGTIDなのか、ソースインスタンスでの更新によるGTIDなのかを判別可能です。
GTIDは aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
としました。
1 2 3 4 |
$ ~/sandboxes/replica-8023/use -e "stop replica" $ ~/sandboxes/replica-8023/use -e "CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'" $ ~/sandboxes/replica-8023/use -e "start replica" $ ~/sandboxes/replica-8023/use -e "show replica statusG" |
worldを削除してインポートします。
1 |
$ curl -sSkL https://downloads.mysql.com/docs/world.sql.gz | gzip -d -c | ~/sandboxes/source-8023/use --init-command="drop database if exists world" |
指定したGTIDが記録されていることが確認できました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ ~/sandboxes/replica-8023/use -e "select @@gtid_executed" +--------------------------------------------------------------------------------------+ | @@gtid_executed | +--------------------------------------------------------------------------------------+ | 00008024-0000-0000-0000-000000008024:1-44, aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1-12 | +--------------------------------------------------------------------------------------+ $ ~/sandboxes/replica-8023/use -e "show binlog events" | grep Gtid | grep 101 : mysql-bin.000001 615310 Gtid 101 615397 SET @@SESSION.GTID_NEXT= '00008024-0000-0000-0000-000000008024:44' mysql-bin.000001 743594 Gtid 101 743678 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1' mysql-bin.000001 743795 Gtid 101 743879 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:2' mysql-bin.000001 744000 Gtid 101 744084 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:3' mysql-bin.000001 744227 Gtid 101 744311 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:4' mysql-bin.000001 744443 Gtid 101 744529 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:5' mysql-bin.000001 745028 Gtid 101 745115 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:6' mysql-bin.000001 1290879 Gtid 101 1290963 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:7' mysql-bin.000001 1291098 Gtid 101 1291184 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:8' mysql-bin.000001 1292059 Gtid 101 1292145 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:9' mysql-bin.000001 1349937 Gtid 101 1350021 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:10' mysql-bin.000001 1350164 Gtid 101 1350250 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:11' mysql-bin.000001 1350778 Gtid 101 1350865 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:12' |
なお、現在のASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONSの状態については、performance_schema.replication_applier_configuration で確認することができます。
1 2 3 4 5 6 7 8 9 |
mysql > select * from performance_schema.replication_applier_configuration; *************************** 1. row *************************** CHANNEL_NAME: DESIRED_DELAY: 0 PRIVILEGE_CHECKS_USER: NULL REQUIRE_ROW_FORMAT: NO REQUIRE_TABLE_PRIMARY_KEY_CHECK: STREAM ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_TYPE: UUID ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_VALUE: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee |
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS 使用時の注意点
MySQL 5.7では実装されていない
MySQL では2つ以上のバージョンをレプリケーショントポロジに含めることはサポートされません。
この機能の印象からは、動的にGTIDを有効化できないMySQL 5.6をソースとしたケースで使用したくなりますが、本機能はMySQL 5.7にバックポートされておりません。
GTIDセットを転送できない
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS によりレプリケーションされたインスタンスのGTIDセット(gtid_executed)、は他のサーバに転送することができません。
そのため1階層のレプリケーショントポロジになります。
Using ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS on a replication channel is not the same as introducing GTID-based replication for the channel. The GTID set (gtid_executed) from a replica set up with ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS should not be transferred to another server or compared with another server’s gtid_executed set. The GTIDs that are assigned to the anonymous transactions, and the UUID you choose for them, only have significance for that replica’s own use.
ソースのリストア用バックアップ・フェイルオーバ先として利用できない
フェイルオーバ時にこのレプリカをソースに昇格させたり、ソースダウン時にレプリカのバックアップを使用して復旧するケースが考えられますが、ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS が有効なレプリカはそれらの操作がサポートされません。
A replica set up with ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS on any channel cannot be promoted to replace the replication source server in the event that a failover is required, and a backup taken from the replica cannot be used to restore the replication source server. The same restriction applies to replacing or restoring other replicas that use ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS on any channel.
これについては、 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS を指定して CHANGE REPLICATION SOURCEを実行した後、SHOW WARNINGSを実行するとメッセージが表示されます。
1 |
| Note | 4017 | Using ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS creates limitations on the replication topology - you cannot fail over between downstream and upstream servers. Only use this option if it is not possible to enable GTIDs on the source, for instance, because of lack of permissions. If possible, use the procedure for enabling GTID transactions online instead, as described in the documentation. |
GTIDはレプリケートされたイベントがレプリカでコミットされるときに割り当てられる
通常、GTIDはソースでコミットされた時点で割り当てられますが、ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS によるGTIDはレプリカでのコミット時点で適用されます。
マルチスレッドスレ―ブの有効時に slave-preserve-commit-order=1 を設定すると通常ソースインスタンスのコミット順序がレプリカでも厳密に守られますが、上記の仕様により効果がありません。
トランザクションのスキップは、sql_slave_skip_counterを利用可能
基本的にはポジションベースのレプリケーションとなるため、 gtid_nextを使用したスキップ方法ではなく、sql_slave_skip_counterを使用します。
https://dev.mysql.com/doc/refman/8.0/en/replication-administration-skip.html
START REPLICA UNTIL SQL_BEFORE_GTIDSおよび UNTIL_SQL_AFTER_GTIDS は利用不可
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS が有効なレプリケーションチャネルでは上記のオプションは利用できません。
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS関数は利用不可
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS が有効なレプリケーションチャネルでは上記のオプションは利用できません。
まとめ
様々な事情により、デフォルト(=非GTID)のまま本番デプロイしてはみたものの、後々やっぱりGTIDしたい!と考えたことはないでしょうか。
この機能はそのようなケースでよりカジュアルにGTIDを使うことができる機能のように思います。
MySQL 5.7の時点でGTIDのオンライン有効化は可能でしたので、例えば上記のようなケースでも本番環境でGTIDを後から有効化することは可能です。
ですが、本番環境での作業を行うことは様々なハードルがあり大変かもしれません。
そのようなケースでとりあえずGTIDを有効化したレプリカを作って評価する、ということが可能ですので、ぜひカジュアルにGTIDレプリカを構築してみてはいかがでしょうか。