起きた事
本番環境のデータ調査の依頼を受けた。その調査を受ける前に、それとは別で不要データを本番DBから削除する作業をMySQL Workbenchで行っていた。
本番DBで、データ調査を行う際にMySQL WorkbenchでSQLのselectと間違えてdeleteを実行してしまい、Tableを1つ丸ごとDeleteしてしまった。
DELETE FROM posts;
ON DELETE CASCADEが親テーブルに設定されてしまっていたため、さらに4つのTable dataが芋づる式に消えてしまった。
ON DELETE CASCADEの説明としては、この記事がわかりやすかったです。
https://www.dbonline.jp/mysql/table/index11.html
テーブルの構成(テーブル名などは例として挙げていて、実際のものとは多少異なります)
正しい設定
usersテーブルでuserを削除した時に、そのuser_idに紐づいている子テーブルのレコードも一緒に削除されるという設定です。
comments table
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
likes table
CONSTRAINT `likes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
points table
CONSTRAINT `points_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
posts table
CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
今回の間違った設定
usersテーブルの子テーブルposts tableを丸ごと一つ削除してしまった時に、post_idが紐づいているusersのレコードも一緒に削除される。
さらに、そのuser_idに紐づいている子テーブルのレコードも芋づる式に一緒に削除されてしまうという設定。
users table
CONSTRAINT `users_ibfk_1` FOREIGN KEY (`comment_id`) REFERENCES `comments` (`id`) ON DELETE CASCADE
CONSTRAINT `users_ibfk_2` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON DELETE CASCADE
CONSTRAINT `users_ibfk_3` FOREIGN KEY (`like_id`) REFERENCES `likes` (`id`) ON DELETE CASCADE
CONSTRAINT `users_ibfk_4` FOREIGN KEY (`point_id`) REFERENCES `points` (`id`) ON DELETE CASCADE
comments table
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
likes table
CONSTRAINT `likes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
points table
CONSTRAINT `points_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
posts table
CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
問題の対処
今回はRDSのバックアップを毎日取ってあったので、それを復元する事で元の状態に戻す事ができました。
その日の朝10:45位に問題が発生し、RDSを復元できたのは13:00位でした。データ量によって復元時間が変動するかもしれないです。
ミーティング中に起きたので、すぐに問題の報告ができました。
バックアップは大事です。。
再発防止策
・本番環境のDBはマネージャー以上のメンバーのみが編集権限(deleteなど)を持ち、それ以外のメンバーは読み取り専用権限にした。
・そもそも親テーブルにON DELETE CASCADEが設定されているのが、おかしいのでON DELETE CASCADEを親テーブルから取り除いた。
実装された経緯は不明だが、明らかにアンチパターンなので、取り除いた。
感想
エンジニアになってから、今回の一件が起こるまでは一度も大きなミスを起こしたことが無かったので、だいぶ気が緩んでいたと思います。
また、ミーティング中にデータの調査が必要になり、話しながら本番DBを見てしまったのもよくなかったです。
DELETEを実行してしまった時は、頭が真っ白になってしまいましたが、
その後に同僚から「自分もそういう経験はたくさんしてきた。気にしなくていいよ」と言ってもらい、励ましてもらえたのは嬉しかったです。
こうやって失敗もしつつエンジニアとして一歩ずつ成長していくのかなと思うので、今回の失敗を糧に自分の成長に繋げて行けたらと思います!