Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 20.9Mb
PDF (A4) - 21.0Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


17.4.1.15 レプリケーションとシステム関数

一部の関数は条件によっては適切に複製されません。

  • USER()CURRENT_USER() (または CURRENT_USER)、UUID()VERSION()、および LOAD_FILE() 関数は、変更なしで複製されますが、行ベースレプリケーションが有効である場合を除いてスレーブ上での機能に信頼性がありません。(セクション17.1.2「レプリケーション形式」を参照してください。)

    USER() および CURRENT_USER() は、MIXED モード使用時に行ベースレプリケーションを使用して自動的に複製され、STATEMENT モードでは警告を生成します。(セクション17.4.1.7「CURRENT_USER() のレプリケーション」も参照してください。)これは、VERSION() および RAND() にも当てはまります。

  • NOW() の場合、バイナリログはタイムスタンプを含みます。これは、マスター上でこの関数への呼び出しによって戻される値がスレーブに複製されることを意味します。タイムゾーンが異なる MySQL サーバー間で複製するときの予期しない結果を回避するには、マスターとスレーブの両方でタイムゾーンを設定してください。セクション17.4.1.30「レプリケーションとタイムゾーン」も参照してください。

    タイムゾーンが異なるサーバー間で複製するときに発生する可能性のある問題を説明するために、マスターはニューヨークにあり、スレーブはストックホルムにあり、両方のサーバーが現地時間を使用しているものとします。さらに、ここで示すようにマスター上で、テーブル mytable を作成し、このテーブルで INSERT ステートメントを実行してから、テーブルから選択するものとします。

    mysql> CREATE TABLE mytable (mycol TEXT);
    Query OK, 0 rows affected (0.06 sec)
    
    mysql> INSERT INTO mytable VALUES ( NOW() );
    Query OK, 1 row affected (0.00 sec)
    
    mysql> SELECT * FROM mytable;
    +---------------------+
    | mycol               |
    +---------------------+
    | 2009-09-01 12:00:00 |
    +---------------------+
    1 row in set (0.00 sec)

    ストックホルムの現地時間はニューヨークより 6 時間遅れます。このため、スレーブ上で SELECT NOW() を完全に同じタイミングで発行すると、値 2009-09-01 18:00:00 が戻されます。このため、上記の CREATE TABLE および INSERT ステートメントが複製されたあとに、mytable のスレーブコピーから選択すると、mycol に値 2009-09-01 18:00:00 が含まれると予想できます。しかし、これはそうなりません。mytable のスレーブコピーから選択すると、マスターとまったく同じ結果になります。

    mysql> SELECT * FROM mytable;
    +---------------------+
    | mycol               |
    +---------------------+
    | 2009-09-01 12:00:00 |
    +---------------------+
    1 row in set (0.00 sec)

    SYSDATE() 関数は、NOW() とは異なり、レプリケーションに安全ではありません。バイナリログ内で SET TIMESTAMP ステートメントに影響されず、ステートメントベースロギングが使用される場合は非決定的であるためです。行ベースロギングを使用する場合は、これは問題ではありません。

    ほかの方法は --sysdate-is-now オプションを使用することで、SYSDATE()NOW() のエイリアスになります。正しく機能するには、これをマスターとスレーブで行う必要があります。このような場合でも、この関数によって警告が発行されますが、--sysdate-is-now がマスターとスレーブの両方で使用されるかぎり安全に無視できます。

    MySQL 5.5.1 以降では、SYSDATE()MIXED モード使用時に行ベースレプリケーションを使用して自動的に複製され、STATEMENT モードで警告を生成します。(Bug #47995)

    セクション17.4.1.30「レプリケーションとタイムゾーン」も参照してください。

  • 次の制限は、ステートメントベースレプリケーションにのみ適用され、行ベースレプリケーションには適用されません。ユーザーレベルロックを扱う GET_LOCK()RELEASE_LOCK()IS_FREE_LOCK()、および IS_USED_LOCK() 関数は、スレーブがマスター上の並列コンテキストを知ることなく複製されます。したがって、スレーブ上の内容が違ってしまうため、これらの関数を使用してマスターテーブルに挿入しないでください。たとえば、INSERT INTO mytable VALUES(GET_LOCK(...)) などのステートメントを発行しないでください。

    MySQL 5.5.1 以降では、これらの関数は MIXED モード使用時に行ベースレプリケーションを使用して自動的に複製され、STATEMENT モードで警告を生成します。(Bug #47995)

ステートメントベースレプリケーションが有効のときに前述の制限に対する回避策として、問題のある関数結果をユーザー変数に保存して、後続のステートメントでその変数を参照する方法を使用できます。たとえば、次の単一行 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;

ストアドファンクション内で、RAND() は、関数の実行中に 1 回だけ呼び出されるかぎり、正しく複製されます。(関数実行タイムスタンプと乱数シードをマスターとスレーブで同じ暗黙的入力と見なすことができます。)

FOUND_ROWS()ROW_COUNT() 関数がステートメントベースレプリケーションを使用して複製されるときは、信頼性がありません。回避策は、関数呼び出しの結果をユーザー変数に格納してから、INSERT ステートメントでこれを使用することです。たとえば、mytable という名前のテーブルに結果を格納する場合は、普通は次のように実行するかもしれません。

SELECT SQL_CALC_FOUND_ROWS FROM mytable LIMIT 1;
INSERT INTO mytable VALUES( FOUND_ROWS() );

しかし、mytable を複製する場合は、次のように SELECT ... INTO を使用してから変数をテーブルに格納することをお勧めします。

SELECT SQL_CALC_FOUND_ROWS INTO @found_rows FROM mytable LIMIT 1;
INSERT INTO mytable VALUES(@found_rows);

このようにすることで、ユーザー変数はコンテキストの一部として複製され、スレーブ上で正しく適用されます。

これらの関数は、MIXED モード使用時に行ベースレプリケーションを使用して自動的に複製され、STATEMENT モードで警告を生成します。(Bug #12092、Bug #30244)

MySQL 5.6.15 より前は、--replicate-ignore-db--replicate-do-table などのフィルタリングオプションがスレーブで有効になっていた場合、LAST_INSERT_ID() の値は正しく複製されませんでした。(Bug #17234370、BUG# 69861)