bigywater.tech
MySQL / InnoDB · 80

时区与 TIMESTAMP

往TIMESTAMP和DATETIME各存同一条数据,切换三次会话时区去读,看谁真实变了、谁真实没变。

TIMESTAMP随时区变
20:00→07:00,真实内部按UTC存储
DATETIME不随时区变
真实全程12:00:00,只是字面值

做的事:同一条数据,一列TIMESTAMP一列DATETIME,切时区读三次

代码SET time_zone = '+00:00'; INSERT INTO ts_test VALUES (1, '2026-01-01 12:00:00', '2026-01-01 12:00:00'); SELECT ts, dt FROM ts_test WHERE id=1; SET time_zone = '+08:00'; SELECT ts, dt FROM ts_test WHERE id=1; SET time_zone = '-05:00'; SELECT ts, dt FROM ts_test WHERE id=1;

验证:TIMESTAMP真实跟着会话时区变,DATETIME真实纹丝不动

实测 · 本机执行输出
time_zone='+00:00':  ts = 2026-01-01 12:00:00   dt = 2026-01-01 12:00:00
time_zone='+08:00':  ts = 2026-01-01 20:00:00   dt = 2026-01-01 12:00:00   ← ts真实变了,dt真实没变
time_zone='-05:00':  ts = 2026-01-01 07:00:00   dt = 2026-01-01 12:00:00   ← ts真实又变了,dt真实还是没变

插入的是同一条数据,只是读的时候切换了会话的time_zone——TIMESTAMP列真实内部按UTC存储一个绝对时间点,每次显示的时候,都会真实按当前会话时区做一次实时换算;DATETIME真实只是原样存储了插入时写的那串字符,不关心任何时区概念,读出来永远是那串字面值。

结论:这个区别决定了它们各自真实适合存什么

TIMESTAMP真实适合存"世界上唯一确定发生的那个时刻"——比如一条日志真实产生的绝对时间,不管以后用什么时区的服务器去读,看到的都是真实同一个时间点换算出来的本地表示;DATETIME真实适合存"字面意义上的某个时间"——比如一场会议约定在"当地时间9点",这个9点不应该因为读取者所在时区不同而真实变来变去。混用这两种类型是常见的真实错误来源:如果应用服务器和数据库服务器的时区配置不一致,TIMESTAMP的自动换算真实会让同一份数据在不同服务器上显示出不同的值,这在跨时区部署的系统里是一个真实容易踩的坑。

分步演示:三次切换时区,TIMESTAMP和DATETIME的真实反应

每一步都是本文上面用真实SET time_zone跑出来的原始结果。

TIMESTAMP真实随会话时区实时换算
这一步新切换的时区

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),同一行数据的TIMESTAMP和DATETIME列,切换SESSION time_zone对比
    京ICP备2026067502号-1京公网安备11010502063487号