バイナリ ロギングのフォーマットにはそれぞれ、メリットとデメリットがあります。大抵の場合、ミックス ベース レプリケーションのフォーマットで対応でき、データの整合性とパフォーマンスにおいては最適なコンビネーションです。しかし、特定のアップデートや大量データの挿入などを行うときに、レプリケーション フォーマットの違いをメリットとして扱う場合などがあります。そのため、この章では、行ベースとステートメント ベースのそれぞれのフォーマットにおけるメリットとデメリットを概説します。
ステートメント ベース レプリケーションのメリット
バージョン 3.23 以来、MySQLに存在する実証済みテクノロジー
ログ ファイルが小さい。更新や削除が数多くの行に影響する場合は、ログ ファイルが 一段と 小さくなる。少量ログ ファイルはストレージ スペースを節約でき、バックアップも早くできる。
ログ ファイルには変更があったすべてのステートメントが含まれるため、データベースの監査に使える。
ログ ファイルはポイント イン タイムのリカバリなど、レプリケーション目的以外にも使える。項4.9.3. 「任意時点のリカバリ」 参照。
テーブルの行ストラクチャが異なる場合でも、マスタで使っているものよりも新しいバージョンを使用しているスレーブを使用できる。これはマスタのアップグレードはできないが、スレーブの最新バージョンに備わっている機能を活用できるなどの有用性がある。これは、テストや評価などの目的としても有効である。
ステートメント ベース レプリケーションのデメリット
UPDATE
ステートメントのすべてを複製することができない。非決定性の動作
(例:SQL
ステートメントのランダム関数使用時など)
は、ステートメント ベース
レプリケーションを使用している場合は複製が困難である。非決定性のユーザ定義関数
(UDF)
を使用したステートメントの場合、行ベース
レプリケーションでは UDF
の戻り値を複製するだけであることに対して、ステートメント
ベース
レプリケーションでの結果は複製することができない。
非決定性の UDF を使用している場合に、ステートメントが適切に複製されない。(値が与えられたパラメータよりも別のファクタに依存する。)
次の関数を使用するステートメントは正確な複製にならない。
LOAD_FILE()
UUID()
USER()
FOUND_ROWS()
SYSDATE()
(--sysdate-is-now
オプションでサーバを起動した場合を除く)
これ以外の関数での複製は正確である。
(RAND()
、NOW()
、LOAD
DATA INFILE
など)
INSERT ... SELECT
は、行ベース
レプリケーションのときよりも、行レベルのロック数をより必要とする。
(WHERE
節でインデックスを使用していないなどの理由で、テーブル
スキャンを必要とする UPDATE
ステートメントは、行ベース
レプリケーションのときよりも行数をより多くロックしなければならない。
InnoDB
の場合、AUTO_INCREMENT
を使用する INSERT
ステートメントは、干渉しない
INSERT
ステートメントなどもブロックする。.
複雑なクエリの場合、ステートメントの評価および行の更新または挿入を行う前にスレーブで実行する必要がある。行ベース レプリケーションでは、スレーブはクエリ全体ではなく、部分的に違いを適用するためだけに、スレートメントを実行する。
格納機能 (格納プロシージャではない)
を呼び出しステートメントと同一の
NOW()
値で実行する。(これには良し悪しがある)
決定性のある UDF をスレーブに適用しなければならない。
スレーブでの評価にエラーがあった場合、特に複雑なクエリを実行しているときには、ステートメント ベース レプリケーションでは、行への影響があるエラーのマージンが時間をかけてゆっくり増加することがある。
マスタとスレーブは殆ど同一でなければならない。
行 ベース レプリケーションのメリット
すべて複製できる。最も安全なレプリケーションの形式である。
5.1.14 以前のバージョンの MySQL
では、CREATE TABLE
のような DDL
(データ定義言語)
ステートメントはステートメント ベース
レプリケーションを使用して複製します。一方の
DML (Data Manipulation Language)
ステートメントの場合は、GRANT
や REVOKE
ステートメントと同様に行ベース
レプリケーションを使用した複製です。
MySQL 5.1.14 以降では、mysql
データベースは複製されません。mysql
データベースはノード指定型データベースとして考えます。行ベース
レプリケーションはこのテーブルをサポートしません。その代わりに、
GRANT
や REVOKE
といった通常、情報を更新するステートメント、操作トリガ、格納ルーチン/プロシージャ、そしてビューなどすべてをステートメント
ベース
レプリケーションでスレーブへ複製します。
CREATE ... SELECT
のようなステートメントの場合は、CREATE
ステートメントがテーブル定義から生成され、ステートメント
ベースの複製、一方、行挿入は行ベースです。
このテクノロジーは他のデータベース管理システムとほぼ同じで、別システムに関する知識は MySQL でも使える。
多くの場合、主キーを保持しているテーブルにはスレーブにデータを適用する方が速い。
次のタイプのステートメントでは、マスタのロック数が少ない (高い同時並行性) 。
INSERT ... SELECT
AUTO_INCREMENT
で
INSERT
ステートメント
キーを使用しない、またはチェック済み行の殆どを変更しない。
WHERE
節で
UPDATE
または
DELETE
ステートメント。
INSERT
、UPDATE
、DELETE
ステートメント
へのスレーブのロック数が少ない。
将来的に、データをスレーブに適用する複数のスレッドを加えることができる。(SMP マシンとの相性が良い)
行 ベース レプリケーションのデメリット
ログ ファイルが大きい (ケースによってはかなり大きい)
バイナリ ログにはロールバックした大きなステートメントが含まれる。
ステートメントを複製するために、行ベース
レプリケーションを使用するときに (例:
UPDATE
または
DELETE
など)、変更された行のそれぞれがバイナリ
ログに書き込まれなければならない。一方では、ステートメント
ベース
レプリケーションを使用する場合は、そのステートメントだけがバイナリ
ログに書き込まれる、ステートメントが多くの行を変更する場合、行ベース
レプリケーションはバイナリ
ログのより多くのデータを書き込む可能性がある。これらのケースでは、バイナリ
ログはデータを書き込むために長時間ロックされ、これは、同時並行性の問題を偶発する。
大きな BLOB
値を生成する決定性 UDF
は複製速度を著しく低下させる。
どのステートメントが実行できたかを調べるためにログをチェックすることができない。
スレーブがマスタからどのステートメントを受信し、実行したかを知ることができない。
非トランザクション ストレージ エンジンを含め、バルク オペレーションを行う場合、変更はステートメントが実行するものとして適用される。これは、行ベース レプリケーション ロギングの場合、バイナリ ログがステートメント実行中に書き込まれることを示す。一方、マスタでは、テーブルはバルク オペレーションが済むまでロックされているため、これが同時並行性に影響を与えることはない。しかし、スレーブ サーバでは、これらの変更はバルク オペレーションの一部ということを認識しないため、スレーブが変更を適用している間にテーブルがロックされない。
このシナリオでは、SELECT * FROM
table_name
などで、マスタのテーブルからデータを取り戻す場合に、サーバは
SELECT
ステートメントを実行する前に、バルク
オペレーションの完了を待機します。これは読み込むテーブルがロックされているためです。スレーブでは、ロックされていないため、サーバは待機しません。これは、
スレーブ’での 「バルク
オペレーション」
が完了するまで、同一の SELECT
クエリから異なる結果がマスタとスレーブに生じるということです。
この動作は、最終的に変更しますが、それが実現するまでは、このようなシナリオに至る可能性がある場合は、ステートメント ベース レプリケーションを行うことをお勧めします。