MySQL はステートメントベースロギング (SBL)、行ベースロギング (RBL)、または混合形式ロギングを使用します。 使用されるバイナリログのタイプは、ロギングのサイズと効率に影響します。 したがって、行ベースレプリケーション (RBR) とステートメントベースレプリケーション (SBR) のどちらを選択するかは、アプリケーションと環境によって異なります。 このセクションでは、行ベースのフォーマットログを使用する際の既知の問題と、それをレプリケーションで使用するためのいくつかのベストプラクティスについて説明します。
詳細については、セクション17.2.1「レプリケーション形式」およびセクション17.2.1.1「ステートメントベースおよび行ベースレプリケーションのメリットとデメリット」を参照してください。
NDB Cluster レプリケーションに固有の問題 (行ベースレプリケーションに依存) については、セクション23.6.3「NDB Cluster レプリケーションの既知の問題」 を参照してください。
-
一時テーブルの行ベースロギング. セクション17.5.1.31「レプリケーションと一時テーブル」 で説明されているように、行ベース形式または (MySQL 8.0.4) 混合形式を使用する場合、一時テーブルはレプリケートされません。 詳細については、セクション17.2.1.1「ステートメントベースおよび行ベースレプリケーションのメリットとデメリット」を参照してください。
行ベースまたは混合形式を使用する場合、一時テーブルはレプリケートされません。これは、必要がないためです。 また、一時テーブルはそれらを作成したスレッドからのみ読み取れるため、ステートメントベース形式を使用する場合でも、それらを複製することから得られるメリットはまずありません。
一時テーブルが作成されている場合でも、実行時にステートメントベースから行ベースのバイナリロギング形式に切り替えることができます。 ただし、MySQL 8.0 では、前のモードでバイナリログから
CREATE TEMPORARY TABLE
ステートメントが省略されているため、バイナリロギングの行ベースまたは混合形式からステートメントベース形式に切り替えることはできません。MySQL サーバーは、各一時テーブルが作成されたときに有効だったロギングモードを追跡します。 特定のクライアントセッションが終了すると、サーバーは、まだ存在し、ステートメントベースのバイナリロギングが使用されていたときに作成された一時テーブルごとに
DROP TEMPORARY TABLE IF EXISTS
ステートメントをログに記録します。 テーブルの作成時に行ベースまたは混合形式のバイナリロギングが使用されていた場合、DROP TEMPORARY TABLE IF EXISTS
ステートメントはログに記録されません。 MySQL 8.0.4 および 5.7.25 より前のリリースでは、DROP TEMPORARY TABLE IF EXISTS
ステートメントは有効なロギングモードに関係なくログに記録されていました。一時テーブルに関連する非トランザクション DML ステートメントは、ステートメントの影響を受ける非トランザクションテーブルが一時テーブルであるかぎり、
binlog_format=ROW
の使用時に許可されます (Bug #14272672)。 非トランザクションテーブルの RBL と同期. 多くの行が影響を受ける場合、変更のセットは複数のイベントに分割されます。ステートメントがコミットすると、これらのイベントのすべてがバイナリログに書き込まれます。 レプリカで実行すると、関連するすべてのテーブルでテーブルロックが取得され、行がバッチモードで適用されます。 テーブルのレプリカコピーに使用されるエンジンによっては、これが有効な場合と無効な場合があります。
待機時間およびバイナリログサイズ. RBL は各行の変更をバイナリログに書き込むため、そのサイズは急激に増える場合があります。 これにより、ソースと一致するレプリカの変更に必要な時間が大幅に長くなる可能性があります。 アプリケーションでこのような遅延が発生する可能性を意識してください。
バイナリログの読み取り. mysqlbinlog は、
BINLOG
ステートメントを使用してバイナリログ内の行ベースイベントを表示します(セクション13.7.8.1「BINLOG ステートメント」を参照してください)。 このステートメントは base 64 でエンコードされた文字列 (その意味は明白ではありません) としてイベントを表示します。--base64-output=DECODE-ROWS
および--verbose
オプションを付けて呼び出されたときは、mysqlbinlog はバイナリログの内容を人間が読める形式にします。 バイナリログイベントが行ベース形式で書き込まれ、それらを読み取ったりレプリケーションまたはデータベース障害からリカバリしたりしたい場合は、このコマンドでバイナリログの内容を読み取ることができます。 詳細については、セクション4.6.8.2「mysqlbinlog 行イベントの表示」を参照してください。-
バイナリログ実行エラーおよびレプリカ実行モード.
slave_exec_mode=IDEMPOTENT
の使用は一般に、IDEMPOTENT
がデフォルト値である MySQL NDB Cluster レプリケーションでのみ役立ちます。 (セクション23.6.10「NDB Cluster レプリケーション: 双方向および循環レプリケーション」 を参照してください)。slave_exec_mode
がIDEMPOTENT
の場合、元の行が見つからないため RBL からの変更の適用に失敗しても、エラーはトリガーされず、レプリケーションが失敗します。 つまり、ソースとレプリカが同期されなくなるように、更新がレプリカに適用されない可能性があります。slave_exec_mode
がIDEMPOTENT
の場合、RBR での待機時間の問題および非トランザクションテーブルの使用によって、ソースとレプリカがさらに相違する可能性があります。slave_exec_mode
の詳細については、セクション5.1.8「サーバーシステム変数」を参照してください。その他のシナリオでは、通常、
slave_exec_mode
をSTRICT
に設定するだけで十分です。これは、NDB
以外のストレージエンジンのデフォルト値です。 サーバー ID に基づくフィルタリングはサポートされない. サーバー ID に基づいてフィルタ処理するには、
CHANGE REPLICATION SOURCE TO
ステートメント (MySQL 8.0.23 の場合) またはCHANGE MASTER TO
ステートメント (MySQL 8.0.23 の場合) のIGNORE_SERVER_IDS
オプションを使用します。 このオプションは、ステートメントベースおよび行ベースのロギング形式で機能しますが、GTID_MODE=ON
が設定されている場合に使用することは非推奨です。 一部のレプリカに対する変更を除外する別の方法は、UPDATE
およびDELETE
ステートメントでリレーション@@server_id <>
句を含むid_value
WHERE
句を使用することです。 たとえば、WHERE @@server_id <> 1
。 ただし、これは行ベースロギングでは正しく動作しません。 ステートメントフィルタリングにserver_id
システム変数を使用するには、ステートメントベースロギングを使用します。RBL、非トランザクションテーブルおよび停止したレプリカ. 行ベースのロギングを使用している場合、レプリカスレッドが非トランザクションテーブルを更新している間にレプリカサーバーが停止すると、レプリカデータベースが一貫性のない状態になる可能性があります。 このため、行ベース形式を使用して複製されたすべてのテーブルに、
InnoDB
などのトランザクションストレージエンジンを使用することをお勧めします。 レプリカ MySQL サーバーを停止する前にSTOP REPLICA | SLAVE
またはSTOP REPLICA | SLAVE SQL_THREAD
を使用すると、問題の発生を防ぐことができ、使用するロギング形式やストレージエンジンに関係なく常に推奨されます。