MySQL レプリケーションでのステートメントの「安全」とは、ステートメントベース形式を使用してステートメントとその結果を正しく複製できるかどうかのことです。これがステートメントに当てはまる場合、ステートメントは安全と言い、そうでない場合は安全でないと言います。
一般的に、ステートメントが決定的である場合は安全であり、そうでない場合は安全ではありません。ただし、特定の非決定的関数は「安全でない」と見なされません (このセクションの後半の安全でないと見なされない非決定的関数。を参照してください)。また、浮動小数点数学関数 (ハードウェア依存) からの結果を使用するステートメントは、常に安全でないと見なされます (セクション17.4.1.12「レプリケーションと浮動小数点値」を参照してください)。
安全および安全でないステートメントの処理
ステートメントは、ステートメントが安全と見なされるかどうかに応じて、およびバイナリロギング形式 (すなわち、binlog_format
の現在の値) に基づいて異なる方法で処理されます。
行ベースロギングを使用する場合、安全および安全でないステートメントの扱いに違いはありません。
混合形式ロギングを使用する場合、安全でないとフラグされたステートメントは行ベース形式を使用してログが記録され、安全と見なされたステートメントはステートメントベース形式を使用してログが記録されます。
ステートメントベースロギングを使用する場合、安全でないとフラグされたステートメントはこの結果に警告を生成します。安全なステートメントは通常どおりにログが記録されます。
安全でないとフラグされた各ステートメントは警告を生成します。以前は、このようなステートメントが大量にマスターで実行された場合、エラーログファイルが非常に大きくなる可能性がありました。これを回避するため、MySQL は次のように動作する警告抑止メカニズム (MySQL 5.6.7 で導入) を提供します。最近の 50 の ER_BINLOG_UNSAFE_STATEMENT
警告が 50 秒間隔で 50 回超生成された場合、警告抑止が有効になります。有効になっているときは、これによってこのような警告がエラーログに書き込まれることはありません。代わりに、このタイプの警告が 50 個生成されるたびに、「最後の警告が
との注記がエラーログに書き込まれます。50 個の最近のこのような警告が 50 秒以内に発行されるかぎり、これが継続します。頻度がこのしきい値を下回ると、再度通常どおりに警告ログが記録されます。警告抑止は、ステートメントベースロギングでステートメントの安全がどのように判断されるか、および警告がクライアントにどのように送信されるかに影響しません。MySQL クライアントは引き続きこのようなステートメントごとに 1 つの警告を受け取ります。
N
回、最近の S
秒間に繰り返されました」
詳細については、セクション17.1.2「レプリケーション形式」を参照してください。
安全でないと見なされるステートメント 次の特徴を持つステートメントは安全でないと見なされます。
-
スレーブで異なる値を返す可能性があるシステム関数を含むステートメント。 これらの関数には
FOUND_ROWS()
、GET_LOCK()
、IS_FREE_LOCK()
、IS_USED_LOCK()
、LOAD_FILE()
、MASTER_POS_WAIT()
、PASSWORD()
、RAND()
、RELEASE_LOCK()
、ROW_COUNT()
、SESSION_USER()
、SLEEP()
、SYSDATE()
、SYSTEM_USER()
、USER()
、UUID()
、UUID_SHORT()
が含まれます。安全でないと見なされない非決定的関数。 これらの関数は決定的ではありませんが、ロギングおよびレプリケーション目的の場合は安全として処理されます:
CONNECTION_ID()
、CURDATE()
、CURRENT_DATE()
、CURRENT_TIME()
、CURRENT_TIMESTAMP()
、CURTIME()
、LAST_INSERT_ID()
、LOCALTIME()
、LOCALTIMESTAMP()
、NOW()
、UNIX_TIMESTAMP()
、UTC_DATE()
、UTC_TIME()
、およびUTC_TIMESTAMP()
。詳細については、セクション17.4.1.15「レプリケーションとシステム関数」を参照してください。
システム変数への参照 ほとんどのシステム変数は、ステートメントベース形式で正しく複製されません。セクション17.4.1.34「レプリケーションと変数」を参照してください。例外については、セクション5.2.4.3「混合形式のバイナリロギング形式」を参照してください。
UDF UDF が何をするかは制御できないため、それが安全でないステートメントを実行していると推定する必要があります。
-
トリガーまたはストアドプログラムは AUTO_INCREMENT カラムを持つテーブルを更新する。 行が更新される順番がマスターとスレーブで異なる可能性があるため、これは安全ではありません。
また、複合主キーを持つテーブルに、この複合キーの先頭カラムでない
AUTO_INCREMENT
カラムが含まれるテーブルにINSERT
することは、安全ではありません。詳細については、セクション17.4.1.1「レプリケーションと AUTO_INCREMENT」を参照してください。
INSERT DELAYED ステートメント このステートメントは、この行の挿入が並列実行されるステートメントによって差し込まれる可能性があるため、安全でないと見なされます。
-
複数の主キーまたは一意キーを持つテーブルでの INSERT ... ON DUPLICATE KEY UPDATE ステートメント 複数の主キーまたは一意キーを持つテーブルに対して実行されるときのこのステートメントは、安全でないと見なされます (ストレージエンジンがキーをチェックする順番に影響されやすいですが、これは決定的でなく、さらに MySQL Server が更新する行の選択がこれに依存するためです)。
複数の一意キーまたは主キーを持つテーブルに対する
INSERT ... ON DUPLICATE KEY UPDATE
ステートメントは、MySQL 5.6.6 以降のステートメントベースレプリケーションでは安全でないとマークされます。(Bug #11765650、Bug #58637) LIMIT を使用する更新 行の取得順序が指定されていないため、安全でないと見なされます。セクション17.4.1.16「レプリケーションと LIMIT」を参照してください。
ログテーブルへのアクセスまたは参照 システムログテーブルの内容は、マスターとスレーブで異なる可能性があります。
-
トランザクション操作後の非トランザクション操作 トランザクション内で、トランザクション読み取りまたは書き込み後に非トランザクション読み取りまたは書き込みを実行することを許可することは、安全でないと見なされます。
詳細については、セクション17.4.1.31「レプリケーションとトランザクション」を参照してください。
セルフロギングテーブルへのアクセスまたは参照 セルフロギングテーブルへのすべての読み取りと書き込みは、安全でないと見なされます。トランザクション内で、セルフロギングテーブルへの読み取りまたは書き込みに続くステートメントも、安全でないと見なされます。
LOAD DATA INFILE ステートメント MySQL 5.6 以降では、
LOAD DATA INFILE
は安全でないと見なされ、ステートメントベースモードで警告が生成され、混合形式ロギング使用時に行ベース形式に切り替わる原因となります。セクション17.4.1.17「レプリケーションと LOAD DATA INFILE」を参照してください。
追加情報については セクション17.4.1「レプリケーションの機能と問題」を参照してください。