レプリケーション ラグ

このページでは、Cloud SQL リードレプリカのレプリケーション ラグのトラブルシューティングと修正方法について説明します。

概要

Cloud SQL リードレプリカは、グローバル トランザクション識別子(GTID)を使用した MySQL 行ベースのレプリケーションを使用します。変更はプライマリ インスタンスのバイナリログに書き込まれ、レプリカに送信されます。レプリカでは変更を受信し、データベースに適用します。

レプリケーション ラグは、次のようないくつかのシナリオで発生する可能性があります。

  • プライマリ インスタンスが、レプリカに変更を十分な速さで送信できない。
  • レプリカが変更を十分な速さで受信できない。
  • レプリカが変更を十分な速さで適用できない。
network_lag 指標を使用して、プライマリ インスタンスが変更を十分な速さで送信できない、あるいはレプリカが変更を十分な速さで受信できない、という最初の 2 つのシナリオをモニタリングします。

合計ラグは、replica_lag 指標で観測されます。replica_lagnetwork_lag の違いから、レプリカがレプリケーションの変更をすぐに適用できない 3 番目の理由がわかります。これらの指標については、この後のレプリケーション ラグをモニタリングするセクションで説明します。

より高速なレプリカ構成

MySQL レプリカで変更をより高速に適用するには、次の 2 つの方法があります。ユーザーは、次の方法でレプリカを構成できます。

  • 並列レプリケーション
  • 高パフォーマンスのフラッシュ

並列レプリケーション

レプリカに変更を適用する複数のスレッドを同時に使用するようにレプリカを構成すると、並列レプリケーションがレプリケーション ラグに役立つ場合があります。並列レプリケーションの使用については、並列レプリケーションの構成をご覧ください。

高パフォーマンスのフラッシュ

デフォルトでは、Cloud SQL for MySQL は各トランザクションの後に REDO ログをディスクにフラッシュします。高パフォーマンスのフラッシュでは、REDO ログがディスクにフラッシュされる頻度が 1 秒に 1 回ずつ削減されるため、書き込みのパフォーマンスが向上します。

リードレプリカの innodb_flush_log_at_trx_commit フラグを 2 に設定します。また、innodb_flush_log_at_trx_commit フラグを有効にするには、sync_binlog フラグに高い値を設定する必要があります。

このフラグの詳細については、フラグの使用に関するヒントをご覧ください。

リードレプリカに innodb_flush_log_at_trx_commit フラグが設定され、Cloud SQL がクラッシュの可能性を検出すると、Cloud SQL は自動的にレプリカを再作成します。

クエリとスキーマを最適化する

このセクションでは、レプリケーションのパフォーマンスを改善するためによく実行するクエリとスキーマの最適化について説明します。

リードレプリカのクエリ分離レベル

REPEATABLE READSERIALIZABLE のトランザクション分離レベルは、レプリケーションの変更をブロックする可能性のあるロックを取得します。レプリカ内のクエリの分離レベルを下げることを検討してください。READ COMMITTED のトランザクション分離レベルのほうがパフォーマンスが向上する可能性があります。

プライマリ データベースでの長時間実行トランザクション

1 つのトランザクションで多数の行が更新されると、プライマリ インスタンスに適用してからレプリカに送信する必要がある変更の数が急増する可能性があります。これは、多くの行に同時に影響する単一ステートメントの更新または削除が行われると発生します。変更は commit 後にレプリカに送信されます。レプリカの変更が急増し、レプリカのクエリ負荷が高くなると、レプリカのロック競合が発生し、レプリケーション ラグが発生する可能性があります。

大きなトランザクションを複数の小さなトランザクションに分割することを検討してください。

主キーの欠如

Cloud SQL リードレプリカは、行ベースのレプリケーションを使用します。そのため、複製される MySQL テーブルに主キーがない場合、パフォーマンスが低下します。レプリケートされたすべてのテーブルに主キーを設定することをおすすめします。

MySQL 8 以降では、データベースのテーブルに主キーが必要となるように sql_require_primary_key フラグを ON に設定することをおすすめします。

DDL による排他ロック

データ定義言語(DDL)コマンド(ALTER TABLECREATE INDEX など)では、排他的ロックによってレプリカでレプリケーション ラグが発生することがあります。ロックの競合を回避するには、レプリカでクエリの負荷が低いときに DDL の実行をスケジュールすることを検討してください。

レプリカの過負荷

リードレプリカが受信するクエリが多すぎると、レプリケーションがブロックされることがあります。読み取りを複数のレプリカに分割して、各レプリカの負荷を減らすことを検討してください。

クエリの急増を回避するには、アプリケーション ロジックまたはプロキシレイヤ(1 つ使用している場合)でレプリカの読み取りクエリを抑制することを検討してください。

プライマリ インスタンスでアクティビティが急増した場合は、更新を分散させることを検討してください。

モノリシックなプライマリ データベース

プライマリ データベースを垂直方向(または水平方向)に分割して、1 つ以上のラグテーブルが他のすべてのテーブルを抑制しないようにすることを検討してください。

レプリケーション ラグをモニタリングする

replica_lag 指標と network_lag 指標を使用してレプリケーション ラグをモニタリングし、ラグの原因がプライマリ データベース、ネットワーク、レプリカのどれにあるのかを識別できます。

指標説明
レプリケーション ラグ
cloudsql.googleapis.com/database/replication/replica_lag

レプリカの状態がプライマリ インスタンスの状態よりも遅れている秒数。これは、現在の時刻と、現在レプリカに適用されているトランザクションをプライマリ データベースが commit した時点のタイムスタンプとの差です。特に、レプリカが書き込みを受信していても、レプリカがデータベースへの書き込みをまだ適用していない場合、書き込みは遅延として記録される可能性があります。

この指標は、レプリカで SHOW SLAVE STATUS が実行されたときに Seconds_Behind_Master の値をレポートします。詳細については、MySQL リファレンス マニュアルのレプリケーション ステータスの確認をご覧ください。

最後の I/O スレッドエラー番号
cloudsql.googleapis.com/database/mysql/replication/last_io_errno

I/O スレッドが失敗する原因となった最後のエラーを示します。この値がゼロでない場合は、レプリケーションが中断します。このケースはまれですが、発生する可能性はあります。エラーコードが示す内容を理解するには、MySQL のドキュメントをご覧ください。たとえば、プライマリ インスタンスの binlog ファイルが、レプリカが受信する前に削除されている可能性があります。通常、Cloud SQL は、レプリケーションが壊れた場合、レプリカを自動的に再作成します。この last_io_errno 指標からその理由がわかります。

最後の SQL スレッドのエラー番号
cloudsql.googleapis.com/database/mysql/replication/last_sql_errno

SQL スレッドが失敗する原因となった最後のエラーを示します。この値がゼロでない場合は、レプリケーションが中断します。このケースはまれですが、発生する可能性はあります。エラーコードが示す内容を理解するには、MySQL のドキュメントをご覧ください。レプリケーションが中断した場合、Cloud SQL は通常、自動的にレプリカを再作成します。この last_sql_errno 指標からその理由がわかります。

ネットワーク ラグ
cloudsql.googleapis.com/database/replication/network_lag

プライマリ データベースのバイナリログに書き込んでから、レプリカの I/O スレッドに到達するまでにかかる時間(秒)。

network_lag がゼロまたはごくわずかであっても、replica_lag が高い場合は、SQL スレッドがレプリケーションの変更を迅速に適用できないことを示します。

レプリケーションを検証する

レプリケーションが機能していることを確認するには、レプリカに対して次のステートメントを実行します。

mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Queueing master event to the relay log
                  Master_Host: xx.xxx.xxx.xxx
                  Master_User: cloudsqlreplica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.199927
          Read_Master_Log_Pos: 83711956
               Relay_Log_File: relay-log.000025
                Relay_Log_Pos: 24214376
        Relay_Master_Log_File: mysql-bin.199898
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 24214163
              Relay_Log_Space: 3128686571
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: Yes
           Master_SSL_CA_File: master_server_ca.pem
           Master_SSL_CA_Path: /mysql/datadir
              Master_SSL_Cert: replica_cert.pem
            Master_SSL_Cipher:
               Master_SSL_Key: replica_pkey.pem
        Seconds_Behind_Master: 2627
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 321071839
                  Master_UUID: 437d04e9-8456-11e8-b13d-42010a80027b
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: System lock
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 437d04e9-8456-11e8-b13d-42010a80027b:52111095710-52120776390
            Executed_Gtid_Set: 437d04e9-8456-11e8-b13d-42010a80027b:1-52113039508
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.00 sec)

レプリケーションが行われている場合は、Slave_IO_State(最初の列)に Waiting for master to send event または類似のメッセージが表示されます。また、Last_IO_Error フィールドは空です。

レプリケーションが行われていない場合、Slave_IO_State 列にステータス Connecting to master が表示され、Last_IO_Error 列にはステータス error connecting to master cloudsqlreplica@x.x.x.x:3306 が表示されます。

MySQL のドキュメントによると、レプリケーション ラグに関連するその他のフィールドは次のとおりです。

フィールド説明
Master_Log_File
I/O スレッドが現在読み取るソース バイナリ ログファイルの名前。
Read_Master_Log_Pos
I/O スレッドが読み取った現在のソース バイナリ ログファイル内の位置。
Relay_Log_File
SQL スレッドが現在読み込んで実行しているリレーログ ファイルの名前。
Relay_Log_Pos
SQL スレッドが読み取って実行した現在のリレーログ ファイル内の位置。
Relay_Master_Log_File
SQL スレッドによって実行された最新のイベントを含むソース バイナリログ ファイルの名前。

上の例では、Relay_Master_Log_File の値は mysql-bin.199898 です。Master_Log_File の値は mysql-bin.199927 です。数値のサフィックス 199898 は 199927 未満です。これは、レプリカが新しい mysql-bin.199927 ログファイルを受信しましたが、まだ古い mysql-bin.199898 を適用していることを意味します。

この場合、レプリカで SQL スレッドのラグが発生します。

プライマリ データベースに接続して実行することもできます。

  SHOW MASTER STATUS;

このコマンドは、プライマリ データベースに書き込まれているバイナリログ ファイルを表示します。

プライマリ データベースのバイナリログ ファイルがレプリカの Master_Log_File より新しい場合は、I/O スレッドが遅れていることを意味します。レプリカはまだプライマリ データベースから古いバイナリログ ファイルを読み取っています。

I/O スレッドが遅延している場合、network_lag 指標も高くなります。SQL スレッドは遅延しているが、I/O スレッドは遅延していない場合、network_lag 指標はそれほど大きくありませんが、replica_lag は高くなります。

前述のコマンドでは、ラグの発生中にラグの詳細を確認できますが、指標 network_lagreplica_lag を使用すると、ラグが発生した過去の発生期間を確認できます。

遅延レプリカを再作成する

レプリケーションが許容可能な時間内に完了しなかった場合は、遅延レプリカを再作成します。

Cloud SQL では、許容できる時間を超えてレプリケーションにラグがある(または遅延している)場合、その遅延が 5 分以上続く場合に、リードレプリカを再作成するように構成できます。

許容できるレプリケーション遅延を 360 秒未満(6 分)と定義しており、361 秒以上のレプリケーション遅延が 5 分間以上続く場合、プライマリ インスタンスの新しいスナップショットが作成され、このスナップショットを使用してリードレプリカが再作成されます。

遅延リードレプリカを再作成することで、次のメリットがあります。

  • レプリケーション遅延の許容範囲を制御します。
  • レプリケーション遅延のトラブルシューティングに費やす時間を数時間、場合によっては数日間短縮できます。

次の特性が追加で適用されます。

  • 次のバージョンと互換性があります。
    • MySQL 5.7
    • MySQL 8.0
    • MySQL 8.4
  • レプリケーション ラグまたは遅延の許容範囲は秒単位で定義する必要があります。
  • 最小許容値は 300 秒(5 分)です。
  • 最大許容値は 31,536,000 秒(1 年)です。
    • インスタンスで遅延レプリカの再作成を有効にするが、許容できるレプリケーション遅延の最大値を設定しない場合、Cloud SQL ではデフォルト値の 1 年が設定されます。
  • サポートされているインスタンスのタイプ:
    • リードレプリカ
    • クロスリージョン リードレプリカ
    • カスケード レプリカ
  • replicationLagMaxSeconds フィールドに設定する値は、各レプリカ インスタンスに固有です。プライマリ インスタンスに複数のレプリカ インスタンスがある場合は、各レプリカに異なる値を設定できます。
  • レプリカが再作成されると、次のオペレーションが完了するまで、ダウンタイムが発生する可能性があります。
    • レプリケーションが停止している。
    • レプリカが削除されます。
    • プライマリ インスタンスのスナップショットが作成されます。
    • レプリカは、この最新のスナップショットから再作成されます。新しいレプリカは、以前のレプリカと同じ名前と IP アドレスを使用します。そのため、MySQL を停止して再起動する必要があります。
    • 新しいレプリカがデータのレプリケーションを開始します。
  • replicationLagMaxSeconds はインスタンス レベルのフィールドです。各インスタンスには独自の値があります。
  • 同じプライマリ インスタンスに複数のリードレプリカがある場合は、各レプリカの replicationLagMaxSeconds フィールドに一意の値を設定できます。

    レプリカごとに異なる時間しきい値を定義すると、すべてのレプリカが同時に停止するシナリオを回避できます。

遅延レプリカの再作成を有効にする

遅延レプリカの再作成機能は、デフォルトでは無効になっています。インスタンスの作成時に有効にするには、次のいずれかの方法を使用します。

gcloud

gcloud sql instances create コマンドで、
--replication-lag-max-seconds-for-recreate フラグを使用して新しいリードレプリカ インスタンスを作成します。

gcloud beta sql instances create REPLICA_INSTANCE_NAME \
  --master-instance-name=PRIMARY_INSTANCE_NAME \
  --database-version=DATABASE_VERSION \
  --tier=TIER \
  --edition=EDITION \
  --region=REGION \
  --root-password=PASSWORD \
  --replication-lag-max-seconds-for-recreate=REPLICATION_LAG_MAX_SECONDS

ここで

  • REPLICA_INSTANCE_NAME はレプリカ インスタンスの名前です。
  • PRIMARY_INSTANCE_NAME はプライマリ インスタンスの名前です。
  • DATABASE_VERSION: インスタンスのデータベース バージョン。たとえば、MYSQL_8_0_31 です。
  • TIER は、レプリカ インスタンスに使用するマシンタイプです。たとえば、db-perf-optimized-N-4 です。詳細については、カスタム インスタンス構成をご覧ください。
  • EDITION は、レプリカ インスタンスに使用するエディションです。たとえば、ENTERPRISE_PLUS です。詳細については、インスタンスの作成をご覧ください。
  • REGION は、レプリカ インスタンスに使用するリージョンです。たとえば、us-central1 です。
  • PASSWORD は、インスタンスの root パスワードです。
  • REPLICATION_LAG_MAX_SECONDS は、許容できる最大レプリケーション ラグまたは遅延(秒単位)です。たとえば、600 です。最小許容値は 300 秒(5 分)です。最大許容値は 31,536,000 秒(1 年)です。

REST API

replicationLagMaxSeconds フィールドは DatabaseInstance リソースにあります。リクエスト本文に次のフィールドを追加します。

{
  "settings": {
  "replicationLagMaxSeconds" :REPLICATION_LAG_MAX_SECONDS,
  }
  ...
}

ここで

  • REPLICATION_LAG_MAX_SECONDS は、許容できる最大レプリケーション ラグまたは遅延(秒単位)です。たとえば、600 です。

レプリケーション ラグの再作成時間を更新する

インスタンスの設定を表示するには、インスタンスの概要情報を表示するで説明されているいずれかの方法に従って操作してください。

この情報に基づいて、レプリカの再作成前に許容可能として指定したレプリケーション ラグ時間枠を更新するかどうかを選択できます。

gcloud

gcloud sql instances patch コマンドを使用して、レプリケーション ラグに基づいてインスタンスの再作成の期間を更新します。

gcloud beta sql instances patch INSTANCE_NAME \
  --replication-lag-max-seconds-for-recreate=REPLICATION_LAG_MAX_SECONDS

ここで

  • INSTANCE_NAME はインスタンスの名前です。
  • REPLICATION_LAG_MAX_SECONDS は、許容できる最大レプリケーション ラグまたは遅延(秒単位)です。たとえば、700 です。デフォルト値の 1 年にリセットする場合は、31536000 を入力します。最小許容値は 300 秒(5 分)です。最大許容値は 31,536,000 秒(1 年)です。

REST API

ポリシーは、instances.patchinstance.insert を使用して更新できます。

REST API を使用して設定を更新する方法の例については、インスタンスを編集するをご覧ください。

制限事項

遅延レプリカの再作成には、次の制限が適用されます。

  • replicationLagMaxSeconds の値は秒単位でのみ設定できます。
  • 再作成オペレーションの前にリードレプリカに作成されたインデックスは保持されません。インデックスが存在する場合は、レプリカの再作成後にセカンダリ インデックスを作成します。
  • リードレプリカの頻繁な停止を回避するため、再作成はインスタンスごとに 1 日 1 回に制限されています。
  • この機能では、高可用性のリードレプリカと外部サーバーのレプリカはサポートされていません。
  • カスケード レプリカで遅延レプリカの再作成を有効にすると、レプリケーションの整合性を維持するために、Cloud SQL はまずリーフレプリカを再作成します。
  • クロスリージョン レプリカを再作成すると、追加の費用が発生します。
  • Google Cloud コンソールで、遅延レプリカの再作成を有効にすることはできません。

次のステップ: