前回の第24回 GTIDを使用したレプリケーション構成を作成する[1]に続いてGTIDについて紹介します。今回は、レプリケーションがエラーで停止してしまった際の対処方法と、MySQL5.7から可能となったオンラインでのGTIDの有効化について説明します。
特定のトランザクションをスキップする
従来のレプリケーションでは、Duplicate entry
などのエラーにてレプリケーションが停止してしまった場合に、SET GLOBAL sql_slave_skip_counter = N
を使用してトランザクションまたはSQLステートメントをスキップすることで、レプリケーションの継続ができました。しかし、GTIDを使用したレプリケーションではこの構文が使用できません。
GTIDを使用したレプリケーションでの対処方法として、以下の2点があります。
- 空のトランザクションを使用した方法
- gtid_purgedを使用した方法
意図的にレプリケーションがエラーで停止するようにして、スレーブのステータスを確認します。
Retrieved_Gtid_Set: 321e231b-3ce3-11e6-9fe5-0242ac110001:1-12
からトランザクションID:12番目まで、スレーブはマスターから更新情報を受け取っているのがわかります。
Executed_Gtid_Set: 3216e1ef-3ce3-11e6-9fe5-0242ac110003:1,321e231b-3ce3-11e6-9fe5-0242ac110001:1-11
からトランザクションID:11番目までスレーブで実行されたのがわかるので、12番目のトランザクションにてLast_Error: Error 'Duplicate entry
が発生したということです。
それぞれの対処方法で12番目のトランザクションをスキップさせてみます。
空のトランザクションを使用した方法
スレーブで実行します。
セッション変数GTID_NEXT
に対象のGTIDを格納して、空のトランザクションを実行します。その後、GTID_NEXT
にAUTOMATIC
をセットすることでスレーブのバイナリログには12番目のトランザクションに空のトランザクションが記述され、レプリケーションを開始することで、次の13番目のトランザクションをマスターに要求するようになります。
しかし、これではマスターのバイナリログとスレーブのバイナリログの内容が変わってしまうため、レプリケーションを開始する前にスレーブのバイナリログの削除が推奨されています。
FLUSH LOGS
でバイナリログをローテートさせ、それ以前のログを削除します。
そして、レプリケーションを開始させます。
gtid_purgedを使用した方法
gtid_purged
はバイナリログから消去されたすべてのトランザクションのセットを格納するグローバル変数です。gtid_purged
に対して先ほどのスキップさせたいトランザクションを設定します。
実行するとエラーとなりました。gtid_executed
が空欄でなければ設定できないという表示です。gtid_executed
はSHOW SLAVE STATUSのExecuted_Gtid_Set
と同様の値で、これをを空欄にするにはスレーブでRESET MASTER
を実施します。そして、gtid_purged
を設定します。
RESET MASTER
することによりスレーブのバイナリログはリセットされ、指定したトランザクション番号以降(今回の例では13番目)のトランザクションから記述されます。
そして、レプリケーションを開始させます。
MySQL5.7からオンラインでGTIDへ変更することが可能
MySQL 5.7.6以降から従来のレプリケーション構成から、オンラインにてGTIDを使用したレプリケーション構成へ変更が可能です。
今回はMySQL 5.7.13
をyumリポジトリーを使用しインストールして確認しています。事前に従来の方式でレプリケーションを設定しておきます。GTIDが有効でないことを確認します。
[手順1]マスター・スレーブ共にENFORCE_GTID_CONSISTENCY
をWARN
に設定
WARN
にすることで、前回説明したGTIDを使用したレプリケーションの制限事項に該当するワークロードが、エラーログに出力されるようになります。ここで出力されるワークロードが存在した場合は、アプリケーションのコードを直すなど、事前に対応しておきます。
[手順2]マスター・スレーブ共にENFORCE_GTID_CONSISTENCY
をON
に設定
ON
にすることでGTIDを使用したレプリケーションの制限事項に該当するワークロードがエラーログに出力されずにSQLエラーとして実行に失敗するようになります。
[手順3]マスター・スレーブ共にGTID_MODE
をOFF_PERMISSIVE
に設定
OFF_PERMISSIVE
にすることで大きな変化はないですがバイナリログがローテートされます。
[手順4]マスター・スレーブ共にGTID_MODE
をON_PERMISSIVE
に設定
ON_PERMISSIVE
にするとバイナリログがローテートされ、mysqlbinlog
でバイナリログを解析すると、GTID_NEXT
がANONYMOUS
からGTIDが設定されるようになります。
スレーブはSHOW SLAVE STATUSを確認すると、Retrieved_Gtid_Set
とExecuted_Gtid_Set
にGTIDが設定されます。
[手順5]マスター・スレーブ共にステータス変数Ongoing_anonymous_transaction_count
が0
まで待機
これは従来のレプリケーション方式で更新されるステートメントがなくなるまで待つということです。
[手順6]マスター・スレーブ共にFLUSH LOGSを実行する
GTIDを使用したバイナリログのみを残すためにFLUSH LOGS
を実行し、それまでのバイナリログを削除します。GTIDが有効なバイナリログと、それ以外の状態のバイナリログが混ざるとPITRができないためです。よって、GTIDの有効化前にフルバックアップの取得とバイナリログのバックアップをしておくことは大切です。
[手順7]マスター・スレーブ共にGTID_MODE
をON
に設定
GTID_MODE
をON
にします。
[手順8]スレーブでレプリケーションの再接続を一度だけ実行
オンラインでGTIDへ変更と書きましたが一度だけスレーブを停止する必要があります。すでにGTIDを使用したレプリケーションとして稼動していますが、GTIDをベースにレプリケーションを再開できるようにレプリケーションを停止して、MASTER_AUTO_POSITION
を1にしてレプリケーションを開始します。
最後にmy.cnfにGTID設定の記述を追加します。
以上でオンラインでのGTIDの有効化が完了となります。
まとめ
今回は、GTIDを使用したレプリケーション時の特定のトランザクションをスキップする方法と、MySQL5.7から可能となったオンラインでGTIDへ変更方法について説明しました。
MySQLのフェールオーバの自動化を提供するツールmysqlfailover
やmysqlfabric
などは、GTIDを使用したレプリケーションが前提となっています。今後のMySQLの高可用性を保つためにはGTIDが必須であるといえます。