一定の条件下では、特定の機能が複製できないことがあります。
USER()
、CURRENT_USER()
、UUID()
そして LOAD_FILE()
関数は、
変更のない複製を行うため、スレーブでは確実には機能しません。列ベースのレプリケーションが使用可能な場合はこの限りではありません。詳細は、項5.1.2. 「レプリケーション フォーマット」
を参照してください。
ロギングに関してはコマンド
ベースから行ベースに形式移行しないため、混在形式ロギングの初期実行段階の格納関数、トリガそしてこれらを主体とした関数を使用するビューは、混在形式のロギング
モードでは確実に複製されません。たとえば、INSERT
INTO t SELECT FROM v
の v
が
UUID()
を選択するビューの場合、問題を引き起こす可能性があります。この制約は、MySQL
5.1.12 で修正の予定です。
NOW()
ではなく、SYSDATE()
関数の場合は、バイナリ ログの SET
TIMESTAMP
コマンドに影響を受けないこと、そしてコマンド
ベースのロギングが使用された場合に非決定性であることから、レプリケーション
セーフではありません。行ベースのロギングを使用している場合には、この点の心配はありません。もう一つのオプションには、SYSDATE()
が NOW()
のエイリアスになることをもたらす
--sysdate-is-now
オプションでサーバを起動する方法もあります。
以下の制約はステートメント
ベースのレプリケーションを行うときに該当します。行ベースのレプリケーションには該当しません。GET_LOCK()
、RELEASE_LOCK()
、IS_FREE_LOCK()
、IS_USED_LOCK()
などユーザ
レベルでロックを処理する関数の場合には、スレーブはマスタの並列化の前後関係を認識しないまま複製を行います。これにより、スレーブの内容がマスタのものとは異なることになり、これらの関数をマスタのテーブルに挿入するためには使用しないでください。(例:
INSERT INTO mytable VALUES(GET_LOCK(...))
のようなコマンドは使わない)
ステートメント
ベースのレプリケーションが有効である場合は、前述の制約への代替方法として、ユーザ変数に問題を起こす関数を使い、後続のコマンドなどでユーザ変数を参照する方法があります。以下は、INSERT
一行挿入が UUID()
関数に対して問題があるとした場合の例示です。
INSERT INTO t VALUES(UUID());
この問題を回避するには、次のことを行います。
SET @my_uuid = UUID(); INSERT INTO t VALUES(@my_uuid);
このシーケンスのコマンドは@my_uuid
という値がバイナリ ログに INSERT
コマンドより前のユーザ変数イベントとして格納され、INSERT
で使用可能になるため、複製できます。
この考え方は、複数行の挿入に適用できますが、扱いがより複雑になります。そのため、2行挿入の場合は、次のように行うことができます。
SET @my_uuid1 = UUID(); @my_uuid2 = UUID(); INSERT INTO t VALUES(@my_uuid1),(@my_uuid2);
この方法は行数が大きいまたは未知である場合には実用的ではありません。そのため、それぞれの行に関連するユーザ変数が与えられている場合は、次の例で示すようにコマンドを変更することはできません。
INSERT INTO t2 SELECT UUID(), * FROM t1;