LoginSignup
42
29

More than 5 years have passed since last update.

俺のtimestampがこんな挙動なわけがない

Posted at

timestampの挙動が変わっていてどハマリしたので共有。

今回使うテーブル定義

テーブル作るときに使ったクエリ
CREATE TABLE `foobar` (
  (省略)
  `start_at` timestamp NOT NULL COMMENT '開始日時',
  `end_at` timestamp COMMENT '終了日時',
  (省略)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

事件の発端

end_at に値してないのに現在時刻が入っているよ?
という思ってたんと違う挙動をしてたのでいろいろ調べた。

ちなみにこれ自体は勘違いで、NULLのつもりだったけど
実際はNULLもNOT NULLも指定していないので、結果的にNOT NULLになるので正しい挙動。

調査した

show create table でとってみたら下記のような状態になっていた。

実際に動いていたもの
CREATE TABLE `foobar` (
  (省略)
  `start_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '開始日時',
  `end_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '終了日時',
  (省略)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

start_at:
指定してないのに DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
が勝手に追加されていた。
プログラム上、値が絶対に入ることになっていたからどっちでもよかったけど、
想定してたものと挙動が変わるのは怖い。
しかもほかで DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP使ってたので影響あり。

end_at:
NOT NULL DEFAULT '0000-00-00 00:00:00' が勝手に追加されてた。
NOT NULLが設定されたのはNULL, NOT NULLの指定をしてなかったから。
DEFAULT '0000-00-00 00:00:00'は上と同様の挙動で追加されたけど、
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPをもうセットしてたから
DEFAULT '0000-00-00 00:00:00'になったと思われる。

検証1 マイグレーションツールを使ってたせい

仮説

手動でクエリ叩いたわけじゃなくて、マイグレーション使ってたせいでは?

結果

手動でも変わらない

検証2 カラム名のせい

仮説

◯◯atって名前が原因では?
Railsとかで create_at とかよくあるし

結果

カラム名を変えて書き換えてみたが変わらなかった

ALTER TABLE request CHANGE start_at start_time timestamp NOT NULL COMMENT '開始日時';
ALTER TABLE request CHANGE end_at end_time timestamp COMMENT '終了日時';

検証3 デフォルト値が必須になった

仮説

timestampはデフォルト値を入れないと勝手に設定されるようになったのでは?

結果

デフォルト値を設定したらうまくいった

ALTER TABLE request CHANGE start_at start_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '開始日時';
ALTER TABLE request CHANGE end_at end_at timestamp NULL DEFAULT NULL COMMENT '終了日時';

ググった

MySQL 5.6からtimestamp 型の暗黙的なデフォルト値は非推奨とのことで、
5.6.6からの警告も出るようになったらしい
MySQL :: MySQL 5.6 Reference Manual :: 5.1.4 Server System Variables

参照元:
http://www.mk-mode.com/octopress/2013/05/31/mysql-5-6-timestamp-default-warning/

(#゚Д゚)ゴルァ!! しらんがな!!

教訓

  • MySQLがマイナーバージョンアップしたらドキュメントはとりあえず隅々まで読んでおく!!
  • ユニットテストでDBにデータがきちんとInsertされたらOKにしない。Insertされた中身もチェックする (DBの仕様変更で影響が出る場合あり)
42
29
0

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
42
29