MySQL 8.0 リファレンスマニュアル


17.1.7.3 トランザクションのスキップ

レプリケートされたトランザクションのイベントの問題が原因でレプリケーションが停止した場合は、レプリカで失敗したトランザクションをスキップしてレプリケーションを再開できます。 トランザクションをスキップする前に、レプリケーション I/O スレッドと SQL スレッドが停止していることを確認します。

まず、エラーの原因となったレプリケートイベントを特定する必要があります。 エラーの詳細および最後に正常に適用されたトランザクションは、「パフォーマンススキーマ」テーブル replication_applier_status_by_worker に記録されます。 mysqlbinlog を使用して、エラー発生時にログに記録されたイベントを取得して表示できます。 これを行う手順は、セクション7.5「Point-in-Time (増分) リカバリ」 を参照してください。 または、レプリカまたはソース上の SHOW BINLOG EVENTSSHOW RELAYLOG EVENTS を発行できます。

トランザクションをスキップしてレプリカを再起動する前に、次の点を確認します:

  • 不明または信頼できないソースからのレプリケーションを停止したトランザクションですか。 その場合は、レプリカを再起動しないことを示すセキュリティ上の考慮事項がある場合に、原因を調査します。

  • レプリケーションを停止したトランザクションをレプリカに適用する必要がありますか。 その場合は、適切な修正を行ってトランザクションを再適用するか、レプリカ上のデータを手動で調整します。

  • レプリケーションを停止したトランザクションをソースに適用する必要がありましたか。 そうでない場合は、最初に実行されたサーバーでトランザクションを手動で元に戻します。

トランザクションをスキップするには、必要に応じて次のいずれかの方法を選択します:

トランザクションのスキップ後にレプリケーションを再開するには、レプリカがマルチソースレプリカの場合は、FOR CHANNEL 句を指定して START REPLICA | SLAVE を発行します。

17.1.7.3.1 GTID のあるトランザクションのスキップ

GTID が使用されている場合 (gtid_modeON)、コミットされたトランザクションの GTID は、トランザクションの内容がフィルタで除外されてもレプリカに保持されます。 この機能により、GTID 自動配置を使用してソースに再接続したときに、レプリカが以前にフィルタ処理されたトランザクションを取得できなくなります。 また、障害が発生したトランザクションのかわりに空のトランザクションをコミットすることで、レプリカ上のトランザクションをスキップするためにも使用できます。

このトランザクションのスキップ方法は、CHANGE REPLICATION SOURCE TO ステートメントの ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS オプションを使用してレプリケーションチャネルで GTID 割当てを有効にした場合には適していません。

失敗したトランザクションによってワーカースレッドでエラーが生成された場合は、「パフォーマンススキーマ」テーブル replication_applier_status_by_workerLAST_SEEN_TRANSACTION フィールドから GTID を直接取得できます。 トランザクションの内容を確認するには、レプリカまたはソース上の SHOW BINLOG EVENTSSHOW 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 は永続化されますが、トランザクション自体はバイナリログファイルをパージすることによって削除されます。

17.1.7.3.2 GTID のないトランザクションのスキップ

GTID が使用されていないか、段階的に導入されている (gtid_modeOFFOFF_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 と同様にスキップする必要があるイベントをカウントする必要がなく、かわりに再起動する場所を指定できます。

17.1.7.3.2.1 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 句が必要です。 正しいチャネルを指定していることを確認してください。そうしないと、間違ったチャネルでイベントがスキップされます。

17.1.7.3.2.2 CHANGE MASTER TO でのトランザクションのスキップ

前述の他の適切なアクション (セキュリティ上の考慮事項など) の失敗したトランザクションを評価したら、レプリケーションを再開するための適切な位置を表すソースバイナリログ内の座標 (ファイルと位置) を特定します。 これは、問題の原因となったイベントの後のイベントグループの開始、または次のトランザクションの開始です。 レプリケーション 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;

関連キーワード:  トランザクション, スキップ, GTID, イベント, ステートメント, ソース, MASTER, バイナリ, チャネル, グループ