WebサービスのDBに関する失敗談 @Akari207
アドベントカレンダー初めての投稿です!
去年の本番環境でやらかしちゃった人カレンダーの投稿を読みとても面白かったので、
今年は初挑戦させていただきましたw
とあるwebアプリケーションにてDB関連でやらかしたことを2本立てで投稿させていただきます。
1本目: 会員データの電話番号や郵便番号の0を飛ばしちゃった話
会員テーブルを整理することになった時の話です。
当時このテーブルは適切ではないデータ型(length含む)や未使用カラムが、存在していました。
変更用のマイグレーションファイルの作成を行い本番にマイグレートしたときに惨劇は起こっていたのです!
問題となったのは以下のカラム変更
Column | Type |
zipcode_01 | LongText |
zipcode_02 | LongText |
tel_01 LongText | LongText |
tel_02 LongText | LongText |
tel_03 LongText | LongText |
↓ ↓ ↓ ↓ ↓ ↓
Column | Type |
zipcode_01 | Small Int |
zipcode_02 | Small Int |
tel_01 Small Int | Small Int |
tel_02 Small Int | Small Int |
tel_03 Small Int | Small Int |
もう理解できた方は多いと思われますが・・・
この変更を行うと郵便番号や、電話番号の数値の先頭0が飛ばされてしまうのです!
携帯番号は090,080とはじまるので、これが 90, 80になってしまいます。
このことに気がつかず、当時数値データのみのカラムなんだから、数値型にするべきだろうと本番にマイグレーションしてしまいました。
そして、翌日に会員データがおかしいと連絡を受けて発覚しました。
幸いなことに、DBのバックアップがあったのと、電話番号と郵便番号はある程度パターンが決まっているので、桁数などでチェックを行い、0が取り除かれたであろうデータは0を追加してデータの修正を行いました。結果会員データの復旧をすることができました。
最終的に内部スキーマはVarCharで適切なlengthを指定するように変更しました。
惨劇はなぜおこってしまったのか
- 自分が無知であった。また調査・確認が足りていなかった。
- ステージやローカルでも確認をおこなっていたが、作成していたデータは、郵便番号や携帯番号など111など適当にしかいれていなかったので、データのおかしさに気づくことができなかった。
二度と惨劇を起こさないためにどうしたのか
- この経験から郵便番号や電話番号など先頭0に意味があるものはVarCharを使うということを学んだ。
- ステージやローカルなどに適当なデータではなくある程度本番に近い形を想定したデータを作成するようにした。
2本目: 知らずにDBをいじめていた時の話
ユーザが入力したデータ(String)をDBに登録して、同じデータであれば集計していくという改修を行った時の話です。
改修自体はスムーズでした。
入力されたデータをチェックして、同じものがあればcountカラムに対して +1なければ、データを新しく登録するといった内容で、この改修はおわりました。
実装当初時は問題なくスムーズに動いていましたが、その改修から2年ほどたったころに惨劇がおこっていることに気づきました。
DBの負荷が年月が立つことに、増えていってたのです。
アクセス数が単純に増えて行ってたこともあり、全く気づいていませんでした。
サイトはよくダウンするようになり、DBがボトルネックとなっていて、負荷集中時に耐えられなくなっていたのです。
その時に原因に気づきました。
ユーザが入力したデータ(String)をDBに登録して、同じデータであれば集計していくという改修でデータを登録していたテーブルのレコード数が
増えていきレコード数が多くなったため、入力されたデータのチェック処理時のSELECTクエリの実行がすごく重くなっていたのです。
惨劇はなぜおこってしまったのか
- データが増えた時の想定を全くしていなかった
- 本番での運用を想定して処理の仕方を工夫しないといけなかった。今回の場合はデータのチェック処理がまずかった。
二度と惨劇を起こさないためにどうしたのか
- 大量にデータが登録されるテーブルは、開発時に大量のデータを登録して動作を行うようにする。
- 登録処理と集計処理は別にする。=> リアルタイムで必要はなかったため、集計はバッチで行い負荷が少ない時間に行うようにした。
以上。最後まで見ていただきありがとうございました。
WEBエンジニア、特にバックエンドだとDBの扱いが非常に大切になります、機能の実装のための設計にもあてはまりますが、運用に関してはしっていれば、防げることは多くあると思います!
この記事が、1人でも多くのエンジニアの役に立てばいいなと思い苦い思い出ではありますが、投稿させていただきました!
twitterでの活動などもおこなっておりますので、PHPやDBなど技術関係の話をしたい人がいれば是非お気軽に絡んでください!
単語メモ
- length:データの長さのことです。
- マイグレーションファイル:データベースの設計図です。
- VarChar:データベースのフィールド定義などで用いられるデータ型の一つで、可変長の文字列を意味するデータ型です。