ルーク!MySQLではkamipo TRADITIONALを使え!
よくMySQLはゆるふわだから
- 値が勝手に切り詰められる
- エラーが起きずに変な値/日付が入る
- 不正なスキーマが入ってしまう
など言われることがあります。ただそれは、そもそもの設定が悪いのです。(確かに昔デフォルトがゆるふわなのはいけなかったんですが)
ということで、データベースには不正な値が入らないように設定はとにかく厳しくしておくのがオススメです。
じゃあどうするか。
MySQLはSQL Modeによって、その辺りの制約をコントロールすることができます。以前、MySQLのsql-modeで一番厳しいやつはTRADITIONAL、というのを書いたのですが、実はそれだけでは不十分で、TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY
とするのがより安心なようです。
これはkamipoさんに教えてもらいました。
@songmu TRADITIONALは複合モードのなかでいちばん厳しめだけどNO_AUTO_VALUE_ON_ZEROとONLY_FULL_GROUP_BY(こっちは5.7.5からデフォルト)も指定しとくのがぼくのオススメです! https://t.co/MAVMgy9TC0
— Ryuta Kamizono (@kamipo) 2015, 2月 25
覚えられないので僕はこれを"kamipo TRADITIONAL"と呼んでいます。以下も合わせてチェック!
https://github.com/kamipo/etcfiles/blob/master/etc/my.cnf#L28
my.cnfで設定するとともにアプリケーション側でも以下をDB接続時に発行するようにしておくと安心です。
SET SESSION sql_mode='TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY'
my.cnfのsql_modeを本番・開発サーバー・CIサーバー・手元の開発環境で揃えるのは結構難しいので、sql_modeをアプリケーション側で統一的に設定しておいたほうが、変な挙動に悩まされることがなくて安心です。(例えば、手元の環境ではsql_modeがゆるゆるだったので、不正なデータがDBに入ってなんとなくちゃんと動いているように見えてたけど、CIではデータが入らないのでテストが通らないとかそういう環境差異に悩まされない。)
このようにしておくと変なデータもスキーマも入らないので安心。例えば大きなサイズのカラムにユニークキー張ろうとしても死んだりしてくれる。
「アプリケーションは適度に柔らかく、最終防衛ラインであるDBは固く」
というのが、個人的なWebアプリ開発モットー。なので、アプリケーションでガチガチにデータモデリングして、DBは柔らかい入れ物を使うっていうのはナンセンスだと思っている。(もちろんアプリケーションでデータモデリングするなって話ではないです)
コードは変えられるが、不正データは残る。修正も大変。一度変なデータが入ったらそのケアのためのコードがアプリケーションに入ったりして破滅する。
なので、とにかくDBは固くする。アプリでミスって不正なデータが入るくらいだった500になったほうがマシ。というのが個人的な考えです。なので本来は外部キーも使ったほうがいいとは思っていますよ!