mita2 database life

主にMySQLに関するメモです

MEMORYエンジンが勝手にGTIDを進めてた

スレーブの gtid_executed がいつのまにかマスターとずれていることがあって、「スレーブに書き込んだうっかりさんは誰・・・?」と思ったらMEMORYエンジンが犯人だった。

MEMORYエンジンはディスクにはデータを保存せず、メモリ上のみデータを保存する。DBを再起動するとデータは消える。

レプリケーションを組んでいて、マスターだけ再起動したとする。 そうすると、マスターではデータが消えて、スレーブではデータが残ったままになる。
これでは、都合が悪い・・・ということで、MEMORYエンジンを利用している場合、再起動するとDELETE文をバイナリログに追記して整合性を取るようになっている。

マスターサーバーがシャットダウンして再起動すると、その MEMORY テーブルは空になります。マスターはこの影響をスレーブに複製するために、起動後に所定の MEMORY テーブルを最初に使用するときに、空にすべきテーブルの
DELETE ステートメントをバイナリログに書き込むことで、そのテーブルを空にする必要があることをスレーブに通知するイベントのログを記録します。
https://dev.mysql.com/doc/refman/5.6/ja/replication-features-memory.html


マニュアルでは「マスターサーバ」としているが、バイナリログがONになっていると、スレーブでもこの挙動になる。
スレーブを再起動すると、スレーブのバイナリログにDELETE文が書かれ、スレーブのUUIDのGTIDが進む。マスターとgtid_executedが一致しなくなる。

元の状態
マスター(UUID:aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10
スレーブ(UUID:zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10
スレーブ再起動。スレーブのUUID(zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx)のGTIDが進む。
マスター(UUID:aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10
スレーブ(UUID:zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10, zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx:1
もっかいスレーブ再起動
マスター(UUID:aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10
スレーブ(UUID:zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx) のgtid_executed:
aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb:1-10, zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx:1-2

この状態で、ある日、マスターとスレーブを入れ替えるとする。
新スレーブ(旧マスター)は自分に未適用のGTIDのトランザクションを新マスター(旧スレーブ)からレプリケーションしようとする。
上記でいうと、zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx:1-2。
バイナリログが残っていれば、MEMORYエンジンのテーブルがDELETEされる(これはまぁ、いいかもしれない。MEMORYエンジンのデータはいつ消えてもいい前提だし)
もし、バイナリログが残ってないと、「そんなGTIDのイベントのログはもう持ってません~ ┐(´д`)┌ 」とレプリケーションが止まってしまう。。。

新マスターでダミーのコミットを実行し、gtid_executed を無理やり揃えて回避。

SET SQL_LOG_BIN=0;

SET GTID_NEXT='zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx:1';
BEGIN; COMMIT;

SET GTID_NEXT='zzzzzzzz-1111-2222-3333-xxxxxxxxxxxx:2';
BEGIN; COMMIT;

SET GTID_NEXT='AUTOMATIC'