Amazon Web Services ブログ
Amazon RDS for MySQL のパラメータ設定 パート 2: レプリケーション関連のパラメータ
このシリーズの前回のブログ投稿では、Amazon RDS for MySQL のパフォーマンスを調整および最適化するために使用する MySQL パラメータと、それらに関連するベストプラクティスについて説明しました。今回の投稿では、RDS MySQL 環境でのレプリケーション構成とレプリケーションの最適化に使用される最も重要な MySQL パラメータについて説明します。
シングルスレッドおよびマルチスレッドの両方のレプリケーションに関連するパラメータ
以下に、シングルスレッドのレプリケーションとマルチスレッドのレプリケーションの両方に使用できるパラメータと、それぞれを設定するためのベストプラクティスの提案を示します。
sync_binlog
sync_binlog
オプションは、MySQL がバイナリログをディスクにフラッシュする方法をコントロールします。
sync_binlog
のデフォルト値は 1 です。マスターサーバで、sync_binlog
が 0 に設定されているとディスクと同期しません。この場合、他のファイルと同様に、バイナリログの内容をフラッシュするタイミングはオペレーティングシステムに依存します。したがって、この設定は、MySQL がバイナリログ (binlog) をディスクにフラッシュしないようにすることでレプリケーションのパフォーマンスを向上させます。この方法で、最高のパフォーマンスが得られます。
ただし、MySQL がクラッシュした場合、いくつかのトランザクションが失われる可能性があります。通常、確実にレプリカをマスターと同期させるために、レプリカを再構築する必要があります。バックアップを無効にし、「チェーン接続された」リードレプリカがないRDS リードレプリカでは、binlog を同期する必要がないため、sync_binlog
は適用されません。バイナリログが生成されないように、レプリカのバックアップ保存期間を 0 に設定することをお勧めします。
ただし、データの損失を最小限に抑えるには、レプリカソースで sync_binlog
パラメータを 1 に設定する必要があります。設定する最善の値は、パフォーマンスと耐久性のどちらを優先するかによって異なります。
binlog_row_image
binlog_format
パラメータを使用すると、バイナリログでサポートされている 2 つのイベントフォーマットを指定することができます。STATEMENT と ROW です。行ベースのフォーマットを使用すると、非決定性のクエリをログに記録することができるので、レプリカで一時テーブルは作成されません。一方、ステートメントベースのフォーマットは、行ベースのフォーマットよりもコンパクトです。
binlog_row_imag
パラメータを使用して、行ベースのイベントについてバイナリログに記録される情報量をコントロールすることができます。行の状態は、バイナリログの「イメージ」で表されます。どの行ベースのイベントでも、変更前イメージと変更後イメージの 2 種類のイメージがあります。変更が行われる前の行は、変更前イメージによって表されます。変更が行われた後の行は、変更後イメージによって表されます。すべてのイベントに、変更の前後のイメージがあるわけではありません。
次の表は、さまざまな行ベースのイベントとそれらの使用可能なイメージをまとめたものです。INSERT ステートメントは Write_rows
イベントを作成します。
イベントのタイプ | 変更前イメージ | 変更後イメージ |
Write_rows | 含まれる | |
Update_rows | 含まれる | 含まれる |
Delete_rows | 含まれる |
次の例は、mysqlbinlog ユーティリティを使用してこれらのイメージを人間が読める形式で読み取ることで、これらのイメージを詳細に示しています。
以下は、先行する INSERT
、UPDATE
、DELETE
ステートメントによって生成されたイベントに対する mysqlbinlog --base64-output=decode-rows --verbose
コマンドの出力です。where
の後のセクションは、変更前イメージを表しています。SET
の後のセクションは、変更後イメージを表しています。
この INSERT
の例には、変更後イメージがあります。
この UPDATE
の例には、変更前イメージと変更後イメージの両方があります。
この DELETE
の例には、変更前イメージだけがあります。
上記の例では、すべての列の詳細がデフォルト設定で記録されています。binlog_row_image
パラメータは、先行するイベントに対してどの列とイメージを記録するかをコントロールするのに役立ちます。
このパラメータでサポートされている値は次のとおりです。
- full – 変更前イメージと変更後イメージのすべての列をログに記録します。
- minimal – 変更後イメージで変更された列だけと、変更前イメージで行を識別するために必要な列をログに記録します。
- noblob – 変更されていない限り、BLOB 列と TEXT 列を除くすべての列をログに記録します。
以下のセクションでは、これらのフォーマット値について説明します。どのイメージフォーマットを使用するかを決定する際は、これらのフォーマットの利点と欠点、およびユースケースとワークロードへの適用方法を考慮します。
Full
full
の値については、変更前イメージと変更後イメージの両方がある、前の例の update_row
イベントの例を示します。
2 番目の列 val1
は更新されませんが、変更前イメージと変更後イメージに含まれます。
full
イメージを使用する利点は次のとおりです。
- すべてのストレージエンジンが、このフォーマットをサポートしています。
- このフォーマットを使用すると、データ操作言語 (DML) のステートメントをロールバックすることができます。このフォーマットは、行を削除するイベントについて、行の変更前イメージのすべての列をログに記録します。したがって、変更前イメージに記録されている値を再挿入することで、行を再構築することができます。
ただし、binlog_row_image=full
を使用することの欠点は、イベントを記録するためにバイナリログでより多くのスペースが必要になることです。これは、列に BLOB または TEXT の値がある更新ステートメントが多数ある場合に特に問題になります。
Minimal
minimal
オプションは、変更を適用するのに必要な情報だけをログに記録します。
- 変更前イメージ – プライマリキーの値だけが、ログに記録されます。
- 変更後イメージ – 値が変更された列が、ログに記録されます。
上記の挿入、更新、削除の例で、minimal
オプションを使用した場合、3 つのイベントは次のとおりです。
INSERT
の例には、変更後イメージだけがあります。
UPDATE
の例には、変更前イメージと変更後イメージの両方があります。
DELETE
の例には、変更前イメージだけがあります。
上記の例から分かるように、INSERT
ステートメントの性質上、Write_rows
イベントの full
オプションと minimal
オプションの間に違いはありません。ただし、行の更新イベントおよび行の削除イベントに対応する UPDATE
および DELETE
のステートメントで記録されるイメージのサイズは、full オプションよりも minimal オプションの方がはるかに小さくなります。
minimal イメージフォーマットを使用する利点は次のとおりです。
- バイナリログイベントは、
UPDATE
とDELETE
の方が小さくなります。ほとんどの更新が単一の列であり、varchar、char、text、blob、および同様のデータ型を持つ大規模な列が多数ある場合は、かなりの節約になる可能性があります。 - バイナリログが小さいと、スペースを節約するだけでなく、レプリケーションのためのディスク I/O とネットワークトラフィックも少なくなります。
minimal
イメージフォーマットを使用する欠点は次のとおりです。
- このアプローチが機能するのは、明示的なプライマリキーまたは NULL 以外の一意のインデックスを持つテーブルに対してだけです。
- すべての列が変更後イメージに記録されるのではなく、変更された列だけが記録されるため、レプリカインスタンスでの列定義の要件が厳しくなります。以下が要件です。
- 両方のテーブルが同じプライマリキーである。
- データ型が同じである。
- 列の順序が同じである。
- マスターとレプリカに同じ列が必要である。それ以外の場合、レプリカは更新イベントのために通知なしで同期しなくなる可能性があります。
noblob
noblob
イメージは、列が必須または変更された場合にだけ BLOB またはテキスト列が変更後イメージに含まれる点を除いて、full
イメージと同じです。
slave_pending_jobs_size_max
このパラメータは、まだ適用されていないイベントを保持するレプリカワーカーのキューに割り当てられるメモリの最大量を定義します。デフォルト値は 16 MB です。この値は、マスターの max_allowed_packet
の値より小さくしてはなりません (下記参照)。小さくすると、処理しなければならないイベントがマスターから来ているのに、レプリカワーカーのキューが満杯になる原因となります。
max_allowed_packet
マスターとリードレプリカの両方で、max_allowed_packet
に同じ値が設定されていることを確認します。そうでないと、レプリカの max_allowed_packet
の値が低いことによる制約で、レプリケーションの遅延が発生する可能性があります。このトピックについては、接続とタイムアウトに関連するパラメーターについてのブログシリーズの今後の部分で詳しく説明します。
innodb_rollback_on_timeout
このパラメータが指定されていると、トランザクションのタイムアウトにより InnoDB が中断し、実行が成功した最後のクエリだけでなく、トランザクション全体をロールバックします。こうすることで、重複エントリに関連するさまざまなレプリケーションエラーを回避できます。デフォルト値は OFF であり、機能を無効にします。
innodb_flush_log_at_trx_commit
パフォーマンスに関連するパラメータについてのこのブログシリーズのパート 1 で説明したように、レプリカインスタンスで innodb_flush_log_at_trx_commit
を 0 または 2 に設定すると、ログバッファがディスクにフラッシュされる頻度が少なくなります。これにより、ディスク書き込みによるパフォーマンスへの影響が少なくなります。ただし、前述のように、これを実行すると、クラッシュした場合に一部のトランザクションが失われる可能性があるというトレードオフが伴います。
query_cache settings
リードレプリカのクエリキャッシュを無効にすることをお勧めします。お勧めする理由は、リードレプリカがデータベースに書き込むときは、ほとんどの場合クエリキャッシュを無効にする必要があるからです。
クエリキャッシュを無効にするには、query_cache_type
を 0 に、query_cache_size
を 0 に設定します。クエリキャッシュの操作方法の詳細については、このブログシリーズのパート 1 を参照してください。
read_only
このパラメータを使用すると、クライアントからリードレプリカへの更新を許可することができます。デフォルト値は TrueIfReplica
です。レプリカインスタンスの場合、TrueIfReplica
は値を ON (1) に設定し、クライアントからの書き込みアクティビティを無効にします。マスター/ライターインスタンスの場合、TrueIfReplica
は値を OFF (0) に設定し、マスター/ライターインスタンスのクライアントからの書き込みアクティビティを有効にします。
この機能を有効にするには、パラメータグループで read_only
を 1 に設定します。read_only
を 0 に設定してこのパラメータを無効にすると、リードレプリカは書き込み可能になります。ただし、RDS MySQL リードレプリカのベストプラクティスとして、この方法でリードレプリカを長期間書き込み可能に変更することはお勧めしません。この設定は、レプリケーションエラーやデータの整合性に関する問題を引き起こす可能性があります。
log_bin_trust_function_creators
バイナリロギングが有効になっているときに関数、プロシージャ、トリガーを有効にするには MySQL SUPER 権限が必要です。この権限は、RDS MySQL DB インスタンスでは制限されています。ただし、バイナリログが有効になっている場合、RDS MySQL インスタンスで関数、プロシージャ、トリガーを有効にできます。そのためには、log_bin_trust_function_creators
パラメータ値を 1 に設定します。そうしないと、次のようなエラーが発生する可能性があります。
デフォルト値は 0 です。
マルチスレッドレプリケーションだけに関連するパラメータ
以下に、マルチスレッドレプリケーションに関連するパラメータと、それぞれを設定するためのベストプラクティスの提案を示します。
slave_parallel_type
このパラメータは、MySQL バージョン 5.7 から利用可能です。その値は、マルチスレッドレプリケーションが有効になっているときにどのトランザクションを並列実行するかを決定するポリシーを定義します。そのためには、slave_parallel_workers
パラメータにゼロ以外の値を使用します。
このパラメータは、LOGICAL_CLOCK と DATABASE の 2 つの値を持つことができます。デフォルト値は、DATABASE です。LOGICAL_CLOCK が設定されていると、マスターで同じバイナリロググループコミットの一部であるトランザクションが、レプリカで並列実行されます。さらに並列化を提供するために、トランザクション間の依存関係をタイムスタンプを使用して追跡します。
値が DATABASE に設定されている場合、異なるデータベースで実行されているトランザクションは並列に適用されますが、この値ではスキーマ内の並列化は不可能です。この値を適用できるのは、異なるデータベースのデータがパーティション化されていて、マスターで同時に独立して更新される場合です。DATABASE を使用するには、データベース間の制約があってはなりません。
このパラメータに使用する値を決定するには、前述の制約と、スキーマ内かスキーマ間のどちらで並列化するかを検討します。スキーマ内の並列化では、LOGICAL_CLOCK が唯一のオプションです。
slave_preserve_commit_order=1
(後述) を使用するには、slave_parallel_type
に LOGICAL_CLOCK を使用する必要があります。
slave_parallel_type
が LOGICAL_CLOCK であり、slave_preserve_commit_order
が有効になっていると、マルチスレッドスレーブ (MTS) ワーカーが innodb_lock_wait
タイムアウトに等しい秒数の間ハングする可能性があるという既知の問題があります。この問題は MySQL 5.6.3、MySQL Bug 82400 および MySQL Bug 25082593 です。これを回避するには、トランザクション分離レベル READ COMMITTED を使用するようにレプリカを設定します。これを行うには、tx_isolation
パラメータを使用します。
slave_parallel_workers
このパラメータは、トランザクションを並列実行しているレプリカインスタンスのワーカースレッドの数を設定します。デフォルト値は 0 であり、その値はワーカースレッドの並列実行を無効にします。可能な値は、0 〜 1,024 です。
レプリカで並列トランザクション実行を使用すると、レプリケーションのスケーラビリティが向上します。ただし、この方法は、マスターとレプリカの両方が少なくとも MySQL 5.6 以降である場合にのみ機能します。slave_parallel_workers
が 0 より大きい値に設定されていると、トランザクションを再試行できず、slave_transaction_retries
は 0 として扱われます。このパラメータにこの値を設定することは、MySQL 5.6.3 (bug 13334470) では必ずしも正しく受け入れられていませんでした。これは 5.6.4 で修正されています。また、このパラメータが有効になっていると、バグ 84415 が影響を与える可能性があります。
MySQL 5.6 では、パラレルレプリケーションはスキーマごとに 1 つのスレッドしか使用しないため、複数のデータベースがある場合は効果的に使用できます。5.7 では、このアプローチはスキーマ内のワークロードにも使用できます。
slave_parallel_workers
の値を大きくしても、レプリケーションのパフォーマンスは直線的には向上しません。このパラメータの最適な値を推定する方法はワークロードに依存しており、実際のワークロードをシミュレートし、レプリケーションの遅れを監視することによってテストする必要があります。
トランザクションに関連するパフォーマンススキーマの計測を有効にして、実行済みトランザクションを記録することができます。次に、それぞれのレプリケーションスレッドによって実行されたトランザクション数を知るために、パフォーマンススキーマテーブル performance_schema.events_transactions_summary_by_thread_by_event_name
および performance_schema.replication_applier_status_by_worker
を確認します。そうすることは、すべてのスレッドが適切に使用されていることを確認するのに役立ち、必要に応じて slave_parallel_workers の値を調整することができます。詳細については、Percona のこちらのブログ投稿を参照してください。
この値を調整する方法は、ワークロードによって異なります。リードレプリカがどの読み取り操作にも使用されず、スタンバイレプリカとしてのみ使用されている場合は、この値をインスタンスの vCPU の数に設定できます。リードレプリカがスタンバイとしてではなく読み取りワークロードの処理に使用されている場合は、値を設定した後にワークロードをテストします。
slave_preserve_commit_order
このパラメータは、MySQL 5.7 で利用可能です。トランザクションは、レプリカのリレーログに表示されるのと同じ順序でレプリカで実行されます。デフォルト値は 0 であり、この機能を無効にします。
MySQL 5.7 で slave_parallel_type
が LOGICAL_CLOCK に設定されている場合に、マルチスレッドレプリケーションの設定でレプリケーションギャップを回避するために、このパラメータをお勧めします。このパラメータは、決してレプリカがマスターがない状態にならないようにします。
このオプションを使用するには、前提条件として自動バックアップ (したがってバイナリロギング) と log_slave_updates
パラメータを有効にする必要があります。log_slave_updates
パラメータは、デフォルトで有効になっています。レプリケーションインスタンスでバイナリロギングを有効にすると、ストレージの使用率とパフォーマンスに影響する可能性があります。したがって、バイナリロギング (自動バックアップ) の有無にかかわらずレプリケーションをテストすることをお勧めします。
マルチスレッドスレーブオプションが有効になっている場合、トランザクションは並列実行できます。slave_preserve_commit_order
パラメータが設定されている場合、実行中のレプリカは、前のトランザクションがすべてコミットされるまでトランザクションのコミットを待機します。レプリカスレッドが他のワーカースレッドが前のトランザクションをコミットするのを待っている場合、そのステータスは前のトランザクションのコミット待ちとして報告されます。
このオプションが有効になっていない場合、リプレイログから実行される一連のトランザクションにギャップが生じる可能性があります。デフォルト値は 0 であり、このパラメータを無効にします。ただし、この場合、Exec_master_log_pos
は、SQL スレッドが読み取って実行した現在のマスターバイナリログファイルの位置より後ろにあるように見える場合があります。
結論
上記のパラメータは、RDS MySQL のレプリケーションのパフォーマンスと安定性に影響を与える可能性がある最も重要なパラメータです。これらのパラメータについて説明したベストプラクティスに従うことで、MySQL RDS レプリカを最小限の遅延でで実行し、他の運用上の問題を回避することができます。
著者について
Saikat Banjeree は、アマゾン ウェブ サービスのクラウドサポートエンジニアです。