復習の意味を兼ねて書いてみます。今回のテーマはGTIDレプリケーションです。・間違ってスレーブでクエリを実行してしまった・マスターのバイナリログが欠損した・バグを踏んだなどの理由で、レプリケーションが崩れてしまった!ということを経験した方も多いのではないでしょうか。今回は、GTIDレプリケーションの復旧方法について書いてみました。復旧方法として、一番シンプルなのは、スレーブのデータディレクトリを一旦削除し、マスターのデータディレクトリと置き換えることです。この方法は、シンプルで間違いがないですが、マスター・スレーブ共にサービス停止を伴うこと、データの転送にはデータ容量に応じた時間がかかることがデメリットです。slaveで復旧は完了となります。以前のポジションベースのレプリケーションであろうが、同じ事です(4を除いて)。他には、マスターでmysqldumpコマンドを実行してバックアップを取得し、これをスレーブに流し込む、という方法もあります。マスターがInnoDBテーブルしか利用していない、もしくはMyISAMテーブルを利用していても、このテーブルには確実に更新が来ない時間を確保できる場合、mysqldumpコマンドで一貫性のあるバックアップを取得できますので、これを、空っぽにしたスレーブのMySQLに読ませ、マスターに接続し直せばレプリケーション復旧です。所要時間はデータディレクトリの再配置よりも長くなります。これも、ほとんどポジションベースのレプリケーションでも同じです。些細なクエリを誤って実行してしまっただけ、だとか、このクエリさえなかったことにできれば、とかいうシチュエーションでは、それだけのためにデータベースを全て再構築するのは悔しいですよね。そこで、今回は、GTIDレプリケーションでクエリを飛ばす方法を書いてみようと思います。ここで、GTIDレプリケーションを簡単におさらいしておきます。GTIDというのは、65e0efe3-0561-11e4-ab46-000c298f7114:1のような形式で表される、トランザクションに対して振られるIDです。この例で言えば、65e0efe3-0561-11e4-ab46-000c298f7114の部分はサーバのUUIDであり、どのMySQLサーバで実行されたトランザクションであるかを示します。:1の部分は、そのトランザクションの番号です。65e0efe3-0561-11e4-ab46-000c298f7114:1-3835であれば、65e0efe3-0561-11e4-ab46-000c298f7114のUUIDを持つMySQLサーバで実行された、1番から3835番までのトランザクション、ということを意味するわけです。ちなみに、UUIDは各MySQLサーバのデータディレクトリにある、auto.cnfファイルに記載されています。飛ばしたいGTIDを特定し、スレーブでそのGTIDに対応するダミーのトランザクションを実行することによって、スレーブのMySQLは、マスターから来たクエリのGTID(飛ばしたいクエリのもの)は既に自分では実行済み、と判断してくれますので、これによってクエリを飛ばす、と言うことになります。実践に入っていきましょう。databaseするコマンドがマスターで成功、スレーブで失敗する、という状態にすることによって、レプリケーションを崩します。sec)マスターにのみ「hoge」データベースが存在しますが、まだレプリケーションは正常に稼動しています。MySQLではデータ不整合があっても、その不整合を突くようなクエリが投げられない限りはエラーは発生しません。hogeを実行します。status結果ではエラーが表示されます。sec)これで無事(?)レプリケーション障害が発生したので、ここからがレプリケーションの復旧手順です。(ここで、マスターへの更新は続いているものとします)まず、スレーブの状態を確認しましょう。statusの結果から、以下のことが分かります。・バイナリログの受け取りはできているが、実行の段になってつまづいている(Slave_IO_Running、Slave_SQL_Runningより)。・スレーブではGTID:18243番までのクエリが実行済みである(Executed_Gtid_Setより)。・スレーブではGTID:18590番までのクエリを受け取っている(Retrieved_Gtid_Setより、必ずしもクエリは実行されていない)。このことから、マスターで実行された、18244番のクエリが問題になっている可能性が高い、と推察できます。hoge」であることも分かります。ここで、復旧方針決定にあたってはデータをどう整合させるか、という判断が必要になります。hogeのSQLを飛ばせば無事復旧することが見込まれます。状況判断のための情報取得の手段として、バイナリログを確認して前後に実行されたクエリを確認することは有用であると言えます。lessDBのREDOログを覗いているわけなので、大量のデータを開くことになる点に注意してください。mysqlbinlogコマンドはリレーログに対してでも実行できるので、マスターで実行するのがためらわれる場合は、スレーブのリレーログを確認しても良いでしょう。直後に削除されるのを承知で、スレーブにhogeデータベースを作成する手もあります。今回はクエリを飛ばす方法での復旧をしてみたいと思います。slaveコマンドを実行して、レプリケーションを完全停止させておいたほうがいいでしょう。No~~~~~~~~~~(略)~~~~~~~~~~さて、それではスレーブでの18244番トランザクション実行を飛ばしましょう。考え方としては、スレーブで18244番に空トランザクションをダミーとして入れておく、ということになります。通常は自動でセットされるGTID_NEXTパラメータを、一時的に手動設定します。sec)これで、次に実行されるトランザクションのGTIDは18244番、となっていますので、ここで空トランザクションを実行します。sec)GTID_NEXTが自動設定されるよう、設定を元に戻します。65e0efe3-0561-11e4-ab46-000c298f7114:1-18244~~~~~~~~~~(略)~~~~~~~~~~となっており、スレーブのExecuted_Gtid_Setの値から、18244番トランザクションが実行されたと認識されていることが分かります。hoge」クエリは実行されないはずです。65e0efe3-0561-11e4-ab46-000c298f7114:1-18590~~~~~~~~~~(略)~~~~~~~~~~Executed_Gtid_SetがちゃんとRetrieved_Gtid_Setに追いついていますね。Slave_IO_Running、Slave_SQL_RunningがYesになっていることからも、レプリケーションは復旧できた、と考えて良さそうです。以上でレプリケーションの復旧手順は完了です。何らかの理由で、あるトランザクションを飛ばしてレプリケーションを復旧させたい場合はご参考になるかと思います。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。Ushio駆け出しのMySQLエンジニア。OSSを仕事で扱っています。themehall.com。