6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MySQLでうっかり違う行を削除してしまったときにバイナリログから復旧する

Last updated at Posted at 2020-12-14

DELETE FROM テーブル WHERE id=xxのxxを間違ってしまった、みたいなときに軽くバイナリログから復旧する方法です。
そもそもWHERE句を入れてなくて100万件消えたとか、ディスクを読み取り専用にしてextundeleteして、みたいなガチな内容ではありません。

バイナリログってなに?

INSERT/UPDATE/DELETEなどの変更SQLを保存するログファイルです。

MySQLのデータフォルダにデータベース名-bin.000001みたいなファイルがあればバイナリログです。
レプリケーションにも使うので、レプリケーション環境であれば存在するはずです。

バイナリログがなかったら、以下の手段は使えないのでがんばってどうにかしてください。

バイナリログをテキストにする

バイナリログは名前のとおりバイナリなので、そのまま見ようとしても全く読めません。
まずはテキスト形式に変換する必要があります。
環境によっては000001とか000002のように複数のバイナリログファイルがありますが、その場合は更新日時を見てどのあたりが必要なログか確認しましょう。

mysqlbinlog -v /path/to/mysql/database-bin.000001 > /tmp/log.txt

実際はなんだかよくわからないデータも残っていたりするのですが、これで一応人間が読めるテキストファイルになりました。

DELETE文を抽出

cat -n /tmp/log.txt | grep "DELETE FROM `DB名`.`テーブル名`"

これでDELETE文が入っている行が抽出されます。
たくさん見つかった場合は、その中からどこが該当のDELETE文なのかを探す仕事が始まります。

head -n 行数+30 /tmp/log.txt | tail -40

こんなかんじでDELETE文の前後の行を取り出せます。
そしてポイントですが、バイナリログではDELETE文にも全てのカラムの内容が入っています。
すなわち、うっかりDELETEしてしまった中身を取り出すことができます。

あとは取り出せた値をINSERTしなおせば復旧完了です。
めでたし。

未確認

TEXT型は取り出せることを確認していますが、BLOBのようなバイナリ型はこれで取り出せるかはわかりません。

ON DELETE CASCADEなどで巻き込まれて削除された場合にバイナリログがどうなるかは確認していません。

今回は調べる必要がなかったからね。

6
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?