レプリケートされたトランザクションのイベントの問題が原因でレプリケーションが停止した場合は、レプリカで失敗したトランザクションをスキップしてレプリケーションを再開できます。 トランザクションをスキップする前に、レプリケーション I/O スレッドと SQL スレッドが停止していることを確認します。
まず、エラーの原因となったレプリケートイベントを特定する必要があります。 エラーの詳細および最後に正常に適用されたトランザクションは、「パフォーマンススキーマ」テーブル replication_applier_status_by_worker
に記録されます。 mysqlbinlog を使用して、エラー発生時にログに記録されたイベントを取得して表示できます。 これを行う手順は、セクション7.5「Point-in-Time (増分) リカバリ」 を参照してください。 または、レプリカまたはソース上の SHOW BINLOG EVENTS
で SHOW RELAYLOG EVENTS
を発行できます。
トランザクションをスキップしてレプリカを再起動する前に、次の点を確認します:
不明または信頼できないソースからのレプリケーションを停止したトランザクションですか。 その場合は、レプリカを再起動しないことを示すセキュリティ上の考慮事項がある場合に、原因を調査します。
レプリケーションを停止したトランザクションをレプリカに適用する必要がありますか。 その場合は、適切な修正を行ってトランザクションを再適用するか、レプリカ上のデータを手動で調整します。
レプリケーションを停止したトランザクションをソースに適用する必要がありましたか。 そうでない場合は、最初に実行されたサーバーでトランザクションを手動で元に戻します。
トランザクションをスキップするには、必要に応じて次のいずれかの方法を選択します:
GTID が使用中 (
gtid_mode
がON
) の場合は、セクション17.1.7.3.1「GTID のあるトランザクションのスキップ」 を参照してください。GTID が使用されていないか、段階的に導入されている (
gtid_mode
がOFF
、OFF_PERMISSIVE
またはON_PERMISSIVE
) 場合は、セクション17.1.7.3.2「GTID のないトランザクションのスキップ」 を参照してください。CHANGE REPLICATION SOURCE TO
ステートメントのASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
オプションを使用してレプリケーションチャネルで GTID 割り当てを有効にした場合は、セクション17.1.7.3.2「GTID のないトランザクションのスキップ」 を参照してください。 レプリケーションチャネルでASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
を使用することは、チャネルに GTID ベースのレプリケーションを導入することとは異なり、GTID ベースのレプリケーションではそれらのチャネルでトランザクションスキップ方法を使用できません。
トランザクションのスキップ後にレプリケーションを再開するには、レプリカがマルチソースレプリカの場合は、FOR CHANNEL
句を指定して START REPLICA | SLAVE
を発行します。
GTID が使用されている場合 (gtid_mode
が ON
)、コミットされたトランザクションの GTID は、トランザクションの内容がフィルタで除外されてもレプリカに保持されます。 この機能により、GTID 自動配置を使用してソースに再接続したときに、レプリカが以前にフィルタ処理されたトランザクションを取得できなくなります。 また、障害が発生したトランザクションのかわりに空のトランザクションをコミットすることで、レプリカ上のトランザクションをスキップするためにも使用できます。
このトランザクションのスキップ方法は、CHANGE REPLICATION SOURCE TO
ステートメントの ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
オプションを使用してレプリケーションチャネルで GTID 割当てを有効にした場合には適していません。
失敗したトランザクションによってワーカースレッドでエラーが生成された場合は、「パフォーマンススキーマ」テーブル replication_applier_status_by_worker
の LAST_SEEN_TRANSACTION
フィールドから GTID を直接取得できます。 トランザクションの内容を確認するには、レプリカまたはソース上の SHOW BINLOG EVENTS
で SHOW RELAYLOG EVENTS
を発行し、その GTID で始まるトランザクションの出力を検索します。
前述の他の適切なアクション (セキュリティ上の考慮事項など) の失敗したトランザクションを評価した場合、スキップするには、失敗したトランザクションと同じ GTID を持つレプリカで空のトランザクションをコミットします。 例:
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';
レプリカ上にこの空のトランザクションが存在するということは、レプリケーションを再開するために START REPLICA | SLAVE
ステートメントを発行すると、その GTID を持つトランザクションがすでに適用されていることがわかっているため、レプリカは自動スキップ機能を使用して失敗したトランザクションを無視することを意味します。 レプリカがマルチソースレプリカの場合、空のトランザクションのコミット時にチャネル名を指定する必要はありませんが、START REPLICA | SLAVE
の発行時にチャネル名を指定する必要があります。
バイナリロギングがこのレプリカで使用されている場合、レプリカが将来ソースまたはプライマリになると、空のトランザクションがレプリケーションストリームに入ります。 この可能性を回避する必要がある場合は、次の例のようにレプリカバイナリログをフラッシュおよびパージすることを検討してください:
FLUSH LOGS;
PURGE BINARY LOGS TO 'binlog.000146';
空のトランザクションの GTID は永続化されますが、トランザクション自体はバイナリログファイルをパージすることによって削除されます。
GTID が使用されていないか、段階的に導入されている (gtid_mode
が OFF
、OFF_PERMISSIVE
または ON_PERMISSIVE
) 場合に失敗したトランザクションをスキップするには、SET GLOBAL sql_slave_skip_counter
ステートメントを発行して、指定した数のイベントをスキップできます。 または、CHANGE MASTER TO
ステートメントを発行してソースバイナリログの位置を前方に移動することによって、イベントを過ぎてスキップすることもできます。
これらの方法は、CHANGE REPLICATION SOURCE TO
ステートメントの ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
オプションを使用してレプリケーションチャネルで GTID 割当てを有効にした場合にも適しています。
これらの方法を使用する場合は、前述の GTID ベースの方法の場合と同様に、完全なトランザクションをスキップする必要はないことを理解することが重要です。 GTID ベース以外のこれらの方法では、そのようなトランザクションは認識されませんが、かわりにイベントを操作します。 バイナリログはイベントグループと呼ばれる一連のグループとして編成され、各イベントグループは一連のイベントで構成されます。
トランザクションテーブルの場合、イベントグループはトランザクションに対応しています。
非トランザクションテーブルの場合、イベントグループは 1 つの SQL ステートメントに対応しています。
1 つのトランザクションに、トランザクションテーブルと非トランザクションテーブルの両方の変更を含めることができます。
SET GLOBAL sql_slave_skip_counter
ステートメントを使用してイベントをスキップし、結果の位置がイベントグループの途中にある場合、レプリカはグループの最後に達するまでイベントをスキップし続けます。 そのあと、次のイベントグループから実行が開始されます。 CHANGE MASTER TO
ステートメントにはこの機能がないため、イベントグループの開始時にレプリケーションを再開する正しい場所を特定するように注意する必要があります。 ただし、CHANGE MASTER TO
を使用すると、SET GLOBAL sql_slave_skip_counter
と同様にスキップする必要があるイベントをカウントする必要がなく、かわりに再起動する場所を指定できます。
前述の他の適切なアクション (セキュリティ上の考慮事項など) の失敗したトランザクションを評価したら、スキップする必要があるイベントの数をカウントします。 あるイベントは通常、バイナリログ内の 1 つの SQL ステートメントに対応しますが、AUTO_INCREMENT
または LAST_INSERT_ID()
を使用するステートメントはバイナリログ内の 2 つのイベントとしてカウントされることに注意してください。 バイナリログのトランザクション圧縮が使用されている場合、圧縮されたトランザクションペイロード (Transaction_payload_event
) は単一のカウンタ値としてカウントされるため、その内部のすべてのイベントは単位としてスキップされます。
完了したトランザクションをスキップする場合は、イベントをトランザクションの最後までカウントすることも、関連するイベントグループをスキップすることもできます。 SET GLOBAL sql_slave_skip_counter
では、レプリカはイベントグループの最後までスキップし続けることに注意してください。 スキップがスキップされないように、スキップして次のイベントグループまたはトランザクションに移動しないでください。
次のように SET
ステートメントを発行します。ここで、N
はスキップするソースからのイベント数です:
SET GLOBAL sql_slave_skip_counter = N
このステートメントは、gtid_mode=ON
が設定されている場合、またはレプリケーション I/O および SQL スレッドが実行されている場合は発行できません。
SET GLOBAL sql_slave_skip_counter
ステートメントはすぐには影響しません。 次の SET
ステートメントの後に START REPLICA | SLAVE
ステートメントを発行すると、システム変数 sql_slave_skip_counter
の新しい値が適用され、イベントはスキップされます。 その START REPLICA | SLAVE
ステートメントでは、システム変数の値も自動的に 0 に戻されます。 レプリカがマルチソースレプリカの場合は、その START REPLICA | SLAVE
ステートメントを発行するときに FOR CHANNEL
句が必要です。 正しいチャネルを指定していることを確認してください。そうしないと、間違ったチャネルでイベントがスキップされます。
前述の他の適切なアクション (セキュリティ上の考慮事項など) の失敗したトランザクションを評価したら、レプリケーションを再開するための適切な位置を表すソースバイナリログ内の座標 (ファイルと位置) を特定します。 これは、問題の原因となったイベントの後のイベントグループの開始、または次のトランザクションの開始です。 レプリケーション I/O スレッドは、次にスレッドが起動したときに、これらの座標でソースからの読取りを開始し、失敗したイベントをスキップします。 このステートメントではイベントグループが考慮されないため、ポジションが正確に識別されていることを確認してください。
次のように CHANGE MASTER TO
ステートメントを発行します。ここで、source_log_name
は再起動位置を含むバイナリログファイル、source_log_pos
はバイナリログファイルに記述されている再起動位置を表す番号です:
CHANGE MASTER TO MASTER_LOG_FILE='source_log_name', MASTER_LOG_POS=source_log_pos;
レプリカがマルチソースレプリカの場合は、FOR CHANNEL
句を使用して CHANGE MASTER TO
ステートメントの適切なチャネルに名前を付ける必要があります。
このステートメントは、MASTER_AUTO_POSITION=1
が設定されている場合、またはレプリケーション I/O および SQL スレッドが実行されている場合は発行できません。 MASTER_AUTO_POSITION=1
が通常設定されているときにトランザクションをスキップするこの方法を使用する必要がある場合は、ステートメントの発行中に設定を MASTER_AUTO_POSITION=1
に変更してから、変更しなおすことができます。 例:
CHANGE MASTER TO MASTER_AUTO_POSITION=0, MASTER_LOG_FILE='binlog.000145', MASTER_LOG_POS=235;
CHANGE MASTER TO MASTER_AUTO_POSITION=1;