同じトランザクション内にトランザクションおよび非トランザクションステートメントを混在させる 一般的に、レプリケーション環境でトランザクションおよび非トランザクションテーブルの両方を更新するトランザクションは避けるべきです。トランザクション (または一時) および非トランザクションテーブルの両方にアクセスしてそれらに書き込むステートメントを使用することも避けるべきです。
MySQL 5.5.2 以降では、サーバーはバイナリロギングに次のルールを使用します。
トランザクション内の最初のステートメントが非トランザクションである場合、それらはすぐにバイナリログに書き込まれます。トランザクション内の残りのステートメントはキャッシュされ、トランザクションがコミットされるまでバイナリログに書き込まれません。(トランザクションがロールバックされた場合、キャッシュされたステートメントは、ロールバックできない非トランザクション変更を行う場合にのみバイナリログに書き込まれます。それ以外の場合は、それらは破棄されます。)
ステートメントベースロギングの場合、非トランザクションステートメントのロギングは
binlog_direct_non_transactional_updates
システム変数によって影響されます。この変数がOFF
の場合 (デフォルト)、ロギングは上記のとおりになります。この変数がON
の場合、非トランザクションステートメントがトランザクション内のどこで発生しても (最初の非トランザクションステートメントだけではありません)、ただちにロギングが発生します。ほかのステートメントはトランザクションキャッシュに保持され、トランザクションがコミットしたときにログが記録されます。binlog_direct_non_transactional_updates
は行形式または混合形式バイナリロギングに影響しません。
トランザクション、非トランザクション、および混合ステートメント これらのルールを適用する場合、サーバーは、非トランザクションテーブルだけを変更する場合にはステートメントを非トランザクションと見なし、トランザクションテーブルだけを変更する場合にはトランザクションと見なします。MySQL 5.6 では、非トランザクションおよびトランザクションテーブルの両方を参照し、使用されるすべてのテーブルを更新するステートメントは、「混合」 ステートメントと見なされます。(以前の MySQL リリースシリーズでは、非トランザクションおよびトランザクションテーブルの両方を変更するステートメントが、混合と見なされていました。)混合ステートメントは、トランザクションステートメントと同様に、キャッシュされ、トランザクションがコミットするときにログが記録されます。
トランザクションテーブルを更新する混合ステートメントは、次のアクションのいずれかを実行する場合も、安全ではないと見なされます。
トランザクションテーブルを更新または読み取る
非トランザクションテーブルを読み取り、トランザクション分離レベルが REPEATABLE_READ 未満
トランザクション内でトランザクションテーブル更新に続く混合ステートメントは、次のアクションのいずれかを実行する場合、安全ではないと見なされます。
テーブルを更新し、一時テーブルから読み取る
非トランザクションテーブルを更新し、binlog_direct_non_trans_update が OFF
詳細については、セクション17.1.2.3「バイナリロギングでの安全および安全でないステートメントの判断」を参照してください。
混合ステートメントは混合バイナリロギング形式とは関係ありません。
トランザクション内でトランザクションおよび非トランザクションテーブルへの更新が混在している状況で、バイナリログ内のステートメントの順序は正しく、必要なすべてのステートメントがバイナリログに書き込まれます (ROLLBACK
の場合でも)。ただし、最初の接続トランザクションが完了する前に 2 番目の接続が非トランザクションテーブルを更新するときは、ステートメントログが記録される順序が乱れる場合があります。最初の接続によって実行されているトランザクションの状態にかかわらず、2 番目の接続更新が実行された直後に書き込まれるためです。
マスターとスレーブで異なるストレージエンジンを使用する
スレーブ上の非トランザクションテーブルを使用してマスター上のトランザクションテーブルを複製できます。たとえば、InnoDB
マスターテーブルを MyISAM
スレーブテーブルとして複製できます。ただし、これを行う場合、スレーブが BEGIN
ブロックの始めで再起動したために BEGIN
... COMMIT
ブロックの途中でスレーブが停止した場合に問題が発生します。
MySQL 5.6 では、マスター上の MyISAM
テーブルからスレーブ上のトランザクションテーブル (InnoDB
ストレージエンジンを使用するテーブルなど) にトランザクションを複製することも安全です。このような場合 (MySQL 5.5.0 以降)、マスター上で発行された AUTOCOMMIT=1
ステートメントが複製されて、スレーブ上で AUTOCOMMIT
モードが適用されます。
スレーブのストレージエンジンタイプが非トランザクションの場合、トランザクションおよび非トランザクションテーブルへの更新が混在するマスター上のトランザクションは、マスタートランザクションテーブルとスレーブ非トランザクションテーブルの間でデータの不整合が発生する可能性があるため、避けるべきです。つまり、このようなトランザクションはレプリケーションの同期を失って、マスターストレージエンジン独自の動作になる可能性があります。現在のところ、MySQL はこれについて警告を発行しないため、トランザクションテーブルをマスターからスレーブ上の非トランザクションテーブルに複製するときは十分に気を付けるようにしてください。
トランザクション内でバイナリロギング形式を変更する
MySQL 5.5.3 以降では、トランザクションが進行中のときは binlog_format
システム変数は読み取り専用です。(Bug #47863)
各トランザクション (autocommit
トランザクションを含む) は、BEGIN
ステートメントで始まり、COMMIT
または ROLLBACK
ステートメントで終わるかのように、バイナリログに記録されます。MySQL 5.6 では、この真実は、非トランザクションストレージエンジン (MyISAM
など) を使用するテーブルに影響するステートメントにも適用されます。