mita2 database life

主にMySQLに関するメモです

MySQL Shell dumpInstance が一貫性の壊れたバックアップを生成するバグの件

前回のエントリーMySQL Shell の dumpInstance にはバグがあると書きました。 今回は、そのバグについてです。

どんなバグか

バックアップの一貫性が失われるバグです。一貫性が失われるている状態とは、バックアップデータの時間軸がずれていることを指します。 あるレコードは10:00:00の状態だが、別のレコードは10:00:01の状態であるといったケースです。

MySQL Shell 8.0.22 でバグがあることを確認しています(それ以前も同じバグがあるかもしれない、未確認です)

Workaround

このバグには簡単なワークアラウンド(回避策)があります。 プロシージャとファンクションをバックアップ対象外にします。 MySQL Shell でバックアップを取っている人はこのオプションを設定しましょう。

util.dumpInstance("mydump", {routines:false});

このバグはMySQL Shellのバグです。mysqldumpやxtrabackupやら他の方法のバックアップには影響ありません(ご安心ください)。

再現方法

簡単に再現します。このような2つのテーブルにINSERTするトランザクションを連続して実行しながら dumpInstance でバックアップを取ります。

BEGIN
  INSERT INTO db1.t1 (c) VALUES()
  INSERT INTO db2.t1 (c) VALUES()
COMMIT
# 運が良いと再現しないので何度もバックアップします
mysqlsh> \py
mysqlsh> for i in range(10): util.dump_instance('/tmp/bk%s' % i, compression='none')

一貫性が正しく保たれていれば、生成されたバックアップの db1.t1db2.t1 の件数が一致するはずです。 しかし、ズレたバックアップが生成されてしまいます。。。

$ tail -n3 bk5/db*@t1*tsv | less
==> bk5/db1@t1@@0.tsv <==
2222 
2223
2224

==> bk5/db2@t1@@0.tsv <==
2221 
2222
2223

バグの原因

MySQL Shellの dumpInstance は、FLUSH TABLES WITH READ LOCKLOCK TABLES で静止点を設け、その間に各Dumpスレッドが、トランザクションを開始します。 各ダンプスレッドが静止点から開始したトランザクションを使って、データをSELECTすることで一貫性を保ったバックアップを生成する仕組みです。

f:id:mita2db:20201104230031p:plain

よくよく調べると、一部のダンプスレッドではトランザクションを開始したあと、プロシージャをバックアップするため、mysql.proc テーブルのロックをとりに行ってました。 LOCK TABLES は暗黙的にトランザクションをコミットします。これによって特定のダンプスレッドだけ静止点からずれたデータをダンプしてしまう状態になってしまっていました。

f:id:mita2db:20201104230857p:plain

ということで、バグレポを上げています。気になる人は Subscribe しておくと良いでしょう。

MySQL Bugs: #101410: mysqlsh dumpInstance backup consistency is broken