それぞれのバイナリロギングの形式にメリットとデメリットがあります。 ほとんどのユーザーにとって、データの完全性とパフォーマンスの最善の組み合わせが得られるのは、混合レプリケーション形式であるはずです。 ただし、特定のタスクを実行するときにステートメントベースまたは行ベースレプリケーション形式固有の機能を利用する場合、関連するメリットとデメリットのサマリーを記述したこのセクションの情報を使用して、どちらがニーズに最適であるかを決めることができます。
ステートメントベースレプリケーションのメリット
実績のあるテクノロジー。
ログファイルに書き込まれるデータが少ないです。 更新または削除が多くの行に影響を与える場合、これによってログファイルに必要なストレージ容量がかなり少なくなります。 つまり、バックアップの取得とリストアをより短時間で達成できます。
ログファイルには変更があったすべてのステートメントが含まれるため、データベースの監査に使用できます。
ステートメントベースレプリケーションのデメリット
-
SBR にとって安全でないステートメント. データを変更するすべてのステートメント (
INSERT
DELETE
、UPDATE
、REPLACE
ステートメントなど) を、ステートメントベースレプリケーションを使用して複製できるわけではありません。 ステートメントベースレプリケーションを使用する場合、非決定的動作は複製が困難です。 このようなデータ変更言語 (DML) ステートメントの例を次に示します:非決定的な UDF またはストアドプログラムに依存するステートメント。そのような UDF またはストアドプログラムによって返される値は、それに提供されるパラメータ以外の要因に依存するため。 (ただし、行ベースのレプリケーションでは、UDF またはストアドプログラムによって返される値が単にレプリケートされるため、テーブルの行およびデータに対する影響はソースとレプリカの両方で同じです。) 詳細は、セクション17.5.1.16「呼び出される機能のレプリケーション」を参照してください。
ORDER BY
なしでLIMIT
句を使用するDELETE
およびUPDATE
ステートメントは非決定的です。 セクション17.5.1.18「レプリケーションと LIMIT」を参照してください。NOWAIT
またはSKIP LOCKED
オプションを使用する読取りステートメント (SELECT ... FOR UPDATE
およびSELECT ... FOR SHARE
) のロック。 NOWAIT および SKIP LOCKED による読取り同時実行性のロックを参照してください。決定論的 UDF をレプリカに適用する必要があります。
-
次のいずれかの関数を使用するステートメントは、ステートメントベースレプリケーションでは適切に複製できません。
LOAD_FILE()
UUID()
、UUID_SHORT()
USER()
FOUND_ROWS()
SYSDATE()
(ソースとレプリカの両方が--sysdate-is-now
オプションで起動されていない場合)GET_LOCK()
IS_FREE_LOCK()
IS_USED_LOCK()
MASTER_POS_WAIT()
RAND()
RELEASE_LOCK()
SLEEP()
VERSION()
ただし、
NOW()
などを含めてほかのすべての関数はステートメントベースレプリケーションで正しく複製されます。詳細については、セクション17.5.1.14「レプリケーションとシステム関数」を参照してください。
ステートメントベースレプリケーションで正しく複製できないステートメントは、ここに示すもののような警告でログが記録されます。
[Warning] Statement is not safe to log in statement format.
このような場合、類似の警告がクライアントにも発行されます。 クライアントは
SHOW WARNINGS
を使用してそれを表示できます。 INSERT ... SELECT
は、行ベースレプリケーションよりも多くの行レベルロックが必要です。WHERE
句でインデックスが使用されていないためにテーブルスキャンを必要とするUPDATE
ステートメントは、行ベースレプリケーションの場合より多くの行をロックする必要があります。InnoDB
の場合:AUTO_INCREMENT
を使用するINSERT
ステートメントは、競合しないほかのINSERT
ステートメントをブロックします。複雑なステートメントの場合、行が更新または挿入される前に、ステートメントを評価してレプリカで実行する必要があります。 行ベースのレプリケーションでは、レプリカは影響を受ける行のみを変更する必要があり、完全なステートメントは実行しません。
特に複雑なステートメントの実行時にレプリカの評価でエラーが発生した場合、ステートメントベースのレプリケーションによって、影響を受ける行のエラーのマージンが徐々に増加する可能性があります。 セクション17.5.1.29「レプリケーション中のレプリカエラー」を参照してください。
ストアドファンクションは、呼び出し元のステートメントと同じ
NOW()
値で実行します。 ただし、これはストアドプロシージャーには当てはまりません。決定論的 UDF をレプリカに適用する必要があります。
テーブル定義は、ソースとレプリカで (ほぼ) 同一である必要があります。 詳細については、セクション17.5.1.9「ソースとレプリカで異なるテーブル定義を使用したレプリケーション」を参照してください。
MySQL 8.0.22 の時点では、(結合リストまたはサブクエリーを介して) MySQL 付与テーブルからデータを読み取るが、変更しない DML 操作は、MySQL 付与テーブルに対する非ロック読取りとして実行されるため、ステートメントベースのレプリケーションでは安全ではありません。 詳細は、テーブル同時実行性の付与を参照してください。
行ベースレプリケーションのメリット
-
すべての変更を複製できます。 これはもっとも安全な形式のレプリケーションです。
注記GRANT
、REVOKE
およびトリガー、ストアドルーチン (ストアドプロシージャーを含む) およびビューの操作など、mysql
システムスキーマ内の情報を更新するステートメントはすべて、ステートメントベースレプリケーションを使用してレプリカにレプリケートされます。CREATE TABLE ... SELECT
などのステートメントの場合、CREATE
ステートメントはテーブル定義から生成されてステートメントベース形式を使用して複製される一方、行挿入は行ベース形式を使用して複製されます。 -
次のタイプのステートメントでは、ソースで必要な行ロックが少なくなるため、同時実行性が高くなります:
INSERT ... SELECT
AUTO_INCREMENT
付きのINSERT
ステートメントキーを使用しないまたは検査された行のほとんどを変更しない
WHERE
句付きのUPDATE
またはDELETE
ステートメント。
INSERT
、UPDATE
またはDELETE
ステートメントのレプリカで必要な行ロックが少なくなります。
行ベースレプリケーションのデメリット
RBR では、ログに書き込む必要があるデータが増える可能性があります。 ステートメントベースレプリケーションでは、DML ステートメント (
UPDATE
、DELETE
ステートメントなど) を複製するためにステートメントだけをバイナリログに書き込みます。 一方、行ベースレプリケーションでは変更されたすべての行をバイナリログに書き込みます。 ステートメントが多くの行を変更する場合、行ベースレプリケーションは非常に多くのデータをバイナリログに書き込む可能性があります。このことはロールバックされるステートメントにも当てはまります。 これは、バックアップの作成およびリストアにさらに時間がかかる可能性があることも意味します。 また、データを書き込むためにバイナリログがロックされる時間が長くなるため、並列性の問題が発生する場合があります。binlog_row_image=minimal
を使用すると、デメリットを大幅に削減できます。大きな
BLOB
値を生成する決定的 UDF の場合は、ステートメントベースレプリケーションより行ベースレプリケーションの方が複製に時間がかかります。 これは、データを生成するステートメントではなく、BLOB
カラム値がログに書き込まれるためです。-
レプリカでは、ソースから受信して実行されたステートメントは表示されません。 ただし、オプション
--base64-output=DECODE-ROWS
および--verbose
を付けて mysqlbinlog を使用すると、何のデータが変更されたかがわかります。または、
binlog_rows_query_log_events
変数を使用します。これを有効にすると、-vv
オプションが使用されたときに、Rows_query
イベントとそのステートメントが mysqlbinlog 出力に追加されます。 MyISAM
ストレージエンジンを使用するテーブルの場合、INSERT
ステートメントをバイナリログに行ベースのイベントとして適用するときは、ステートメントとして適用するときよりも強力なロックがINSERT
ステートメントのレプリカに必要です。 これは、MyISAM
テーブルでの同時挿入が、行ベースレプリケーションを使用するときにサポートされないことを意味します。