2017年7月19日水曜日

GTIDを有効にしているのにレプリケーションのポジションがズレる場合

TL;DR


GTIDを有効にしてレプリケーションを組んでいる( MASTER_AUTO_POSITION=1 )場合、実行済みのトランザクションのGTIDは gtid_executed に記録される。
そしてI/Oスレッドは 自分のgtid_executedに含まれていない イベントがあれば寄越せ、というように接続時にマスターに要求するし、仮に自分のgtid_executedに含まれているイベントが寄越されてもSQLスレッドが同じGTIDのイベントの二重適用を防ぐ。
これでレプリケーションのポジションはズレない。ズレるはずがない。
gtid_executedが間違っていなければ
じゃあどこでgtid_executedが間違うのか。
  1. gtid_executedはそもそもサーバー変数で、オンメモリーだ。取り敢えずのところ、mysqldが停止しなければgtid_executedは間違わない(はず。間違うならそれはバグだ)
  2. mysqldが停止した場合、サーバー変数のgtid_executedは当然値が失われる。その場合、バイナリーログ(openしてれば)とmysql.gtid_executedから復元する
  3. mysql.gtid_executedはバイナリーログをopenしている場合はバイナリーログのスイッチ時とmysqldのシャットダウン時、openしていない場合はコミットの都度書き込む。マスターは確実にバイナリーログをopenしているので前者の動きになる
  4. ところで、ここに稼働中のマスターサーバーから取ったXtraBackupがあるじゃろ?
  5. トランザクションで保護するからmysql.gtid_executedテーブルはXtraBackup開始時の値が保管されるじゃろ?
  6. XtraBackupはバイナリーログは取らないじゃろ? (あればbinlogに記録されている分からgtid_executedをリカバってくれる)
  7. リストアして CHANGER MASTER TO .. MASTER_AUTO_POSITION= 1 するとサクッとズレる
  8. _| ̄|○
リストアしてから CHANGE MASTER TO .. の前に、 RESET MASTER で gtid_executedの中身を吹っ飛ばし、 SET GLOBAL gtid_purged = '..' で設定するのが正しいと思う。
MySQL 5.7.18とそれ以前のmysqldumpでも同じことが起きる( --all-database でmysql.gtid_executedをダンプしてしまう)し、事実 去年隣にいた人 はmysqldumpで踏んでた。これは最近リリースされたMySQL 5.7.19のmysqldumpでは直っているそうだけれども。
まあ何にせよ注意。。

0 件のコメント :

コメントを投稿