以下、サポートされていることとサポートされていないことについて説明します。
レプリケーションは、AUTO_INCREMENT
、LAST_INSERT_ID()
、および
TIMESTAMP
の値で正しく実行される。
USER()
関数および
LOAD_FILE()
関数は変更なしにレプリケートされるため、スレーブではうまく機能しない。これは、4.1.1
より古いバージョンのスレーブの
CONNECTION_ID()
にも当てはまる。
MySQL 4.1 の新しい
PASSWORD()
関数は、4.1.1
以降のマスタでは正常にレプリケートできるが、スレーブが
4.1.0
以降であることが前提条件となる。スレーブが古く、PASSWORD()
を 4.1.x
マスタからレプリケートする必要がある場合、--old-password
オプションでマスタを起動する。
SQL_MODE
、UNIQUE_CHECKS
、SQL_SELECT_LIMIT
、SQL_AUTO_IS_NULL
、TABLE_TYPE
の各変数は現在のところレプリケートされない。FOREIGN_KEY_CHECKS
はバージョン 4.0.14
からレプリケートされる。
マスタとスレーブでは、同じキャラクタセット(--default-character-set
)を使用する必要がある。そうしないと、マスタのキャラクタセットで一意と認識されるキーが、スレーブのキャラクタセットでは一意と見なされない場合があるため、スレーブで重複キーエラーが発生する可能性がある。
マスタでトランザクションテーブルを使用し、スレーブで非トランザクションテーブルを使用(同一テーブルで)している場合、スレーブが
BEGIN/COMMIT
ブロックの途中で停止すると、次回スレーブが
BEGIN
ブロックの始めから開始するという問題が発生する。
この問題は近い将来、解決する予定である。
ユーザ変数を使用する更新クエリは、3.23 および 4.0 で正常にレプリケートされない。これは 4.1 で解決されている。注意: バージョン 5.0 以降、ユーザ変数名の大文字と小文字は区別されなくなるので、5.0 とその前のバージョンとの間でレプリケーションを設定する際は注意が必要となる。
マスタとスレーブが両方とも 4.1.1 以降の場合、スレーブは SSL を使用してマスタに接続できる。
実際に発生した例を聞いたことはないが、データの変更が非決定論的、つまりクエリオプティマイザの判断で行われるようにクエリが設計されている場合(レプリケーション外でも、通常、この方法は適切な方法でない)、論理的には、マスタとスレーブのデータが異なる可能性がある。詳細については、項1.8.6.2. 「MySQL の未解決のバグと設計上の問題」 を参照のこと。
MySQL 4.1.1
より前では、FLUSH
、ANALYZE
、OPTIMIZE
、REPAIR
の各コマンドはバイナリログに保存されず、したがってスレーブにレプリケートされない。これらのコマンドは何も変更しないため、通常は問題ではない。しかし、GRANT
ステートメントを使用せずに MySQL
権限テーブルを直接更新し、mysql
権限テーブルをレプリケートした場合、新しい権限を有効化するには、スレーブで
FLUSH PRIVILEGES
を実行することが必要となる。また、MERGE
テーブルに含まれる MyISAM
テーブルの名前を変更するときに FLUSH
TABLES
を使用した場合、スレーブで
FLUSH TABLES
を手動で実行する必要がある。 MySQL 4.1.1
以降、NO_WRITE_TO_BINLOG
(またはエイリアスの
LOCAL
)を指定しない限り、これらのコマンドはバイナリログに書き込まれる(FLUSH
LOGS
、FLUSH
MASTER
、FLUSH
SLAVE
、FLUSH TABLES WITH READ
LOCK
は除く)。
構文例については、項4.6.4. 「FLUSH
構文」
を参照のこと。
MySQL は、1
つのマスタと複数のスレーブ構成のみサポートする。将来は、カレントマスタで問題が発生した場合にマスタを自動変更するアルゴリズムを追加する予定である。また、複数のスレーブに
SELECT
クエリを送信することによって負荷分散を行う
``エージェント''
処理も導入する予定である。
テンポラリテーブルもレプリケートされる。ただし、スレーブスレッドだけでなくスレーブサーバもシャットダウンし、その際、まだスレーブで実行していない更新ステートメントで使用されるテンポラリテーブルをレプリケートしていた場合、そのテンポラリテーブルはレプリケートされない。スレーブをシャットダウンすると、次回、スレーブを起動したとき、更新に必要なテンポラリテーブルは利用できない。この問題を回避するには、テンポラリテーブルが開いている間、スレーブをシャットダウンしない。代わりに、以下の手順を実行する。
STOP SLAVE
ステートメントを実行する。
SHOW STATUS
を使用して、Slave_open_temp_tables
変数の値をチェックする。
値が 0 であれば、mysqladmin
shutdown
コマンドを実行してスレーブをシャットダウンする。
値が 0 でなければ、START
SLAVE
でスレーブスレッドを再開する。
次回も上記手順を繰り返す。
この問題は、近い将来解決する予定である。
log-slave-updates
を有効にすれば、循環的なマスタ/スレーブ関係でサーバを接続しても安全である。注意:
ただし、異なるサーバ間で、違った手順で行った更新が引き起こすであろう問題を処理するように、クライアントコードを記述しておかなければ、多くのクエリはこの種のセットアップで正しく機能しない。
つまり、以下のようなセットアップが可能である。
A -> B -> C -> A
サーバ ID は、バイナリログイベント内でエンコードされる。A は、A が作成したイベントを認識できるので、A はそのイベントを実行せず、無限ループは発生しない。しかし、この循環セットアップは、テーブル間で競合が生じない更新だけを行っている場合にしか機能しない。つまり、A と C にデータを挿入する場合、C でのレコード挿入と競合するキーのレコードを A に挿入することはできない。また、更新が適用される順序が重要な場合、2 つのサーバで同じ複数のレコードを更新することもできない。
スレーブでクエリにエラーが発生すると、スレーブの
SQL
スレッドは強制終了し、スレーブエラーログにメッセージが書き込まれる。この場合、スレーブに手動で接続し、エラーの原因(テーブルが存在しないなど)を解決し、START
SLAVE
を実行する。
マスタへの接続が失われた場合、スレーブはすぐに再接続を試行する。それが失敗した場合、スレーブは
master-connect-retry
秒(デフォルトは
60)ごとに再試行する。このため、マスタをシャットダウンし、しばらく後で再起動しても安全である。スレーブはまた、ネットワーク接続停止にも対応できる。ただし、スレーブがネットワーク停止を認識するのは、マスタから
slave_net_timeout
秒間、何のデータも受け取らなかった後である。そのため、ネットワーク停止の時間が短い場合は、slave_net_timeout
の値を小さくすべきである。 See
項4.6.8.4. 「SHOW VARIABLES
」。
スレーブのシャットダウンをクリーンに行えば、どこでレプリケーションが終了したか記録されるので、安全である。クリーンでないシャットダウンでは、システム終了前にディスクキャッシュが同期化されていない場合は特に、問題が発生する可能性がある。性能の高い無停電電源装置を用意すれば、システムの耐障害性はかなり向上する。
MyISAM
テーブルの非トランザクション性により、テーブルの更新を一部だけ実行してエラーコードを返すクエリが現れる可能性がある。複数レコード挿入で
1
つのレコードがキー制約に違反していた場合や、長い更新クエリが一部のレコードだけを更新した後に強制終了された場合に、発生する。これがマスタで発生した場合、エラーコードが正当で、かつクエリ実行結果も同じエラーコードであったとき以外、スレーブスレッドは終了し、データベース管理者の判断を待つ。このエラーコード確認動作が望ましくない場合は、--slave-skip-errors
オプションで一部(または全部)のエラーを無視できる。このオプションは、MySQL
バージョン 3.23.47 より使用可能。
BEGIN/COMMIT
セグメント内部で、非トランザクションテーブルからトランザクションテーブルを更新する場合、トランザクションがコミットする前に非トランザクションテーブルを変更するスレッドがあれば、バイナリログへの更新が非同期になる。これは、トランザクションのバイナリログへの書き込みがコミット後に行われるためである。
バージョン 4.0.15
より前では、非トランザクションテーブルへの更新は、更新実行後すぐにバイナリログに書き込まれ、トランザクションテーブルへの変更は、COMMIT
時に書き込まれるか、または
ROLLBACK
を使用した場合はまったく書き込まれない。バックアップまたはレプリケーションでバイナリログを使用する場合、同一トランザクションでトランザクションテーブルと非トランザクションテーブルの更新を行う際は、この点に注意しなければいけない。トランザクションテーブルと非トランザクションテーブルの更新が混在したトランザクションでのログ動作は、バージョン
4.0.15
で変更され、この問題は解決された(バイナリログでのクエリの書き込み順序に問題はなくなり、ROLLBACK
の場合でも必要なクエリはすべてバイナリログに書き込まれるようになった)。ただし、最初の接続のトランザクションが完了していない時点で、2
番目の接続が非トランザクションテーブルを更新した場合の問題は残っている(2
番目の接続の更新は実行後すぐ書き込まれるため、順番が混乱する可能性はまだある)。
以下の表は、MySQL 3.23 で問題だったものを MySQL 4.0 で解決した事項です。
LOAD DATA INFILE
は、更新伝達時にデータファイルがマスタサーバにあれば、正しく処理される。
LOAD LOCAL DATA INFILE
はスキップされる。
3.23 では、更新内の RAND()
は正しくレプリケートされなかった。RAND()
が含まれる更新をレプリケートしている場合は、RAND(some_non_rand_expr)
を使用する。 たとえば、RAND()
への引数に UNIX_TIMESTAMP()
を使用できる。これは 4.0 で解決された。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.