now()返回mysql服务器当前系统时间,由time_zone变量决定时区,非客户端或utc时间,与服务器date命令输出一致。

MySQL里NOW()返回的是什么时间?
它返回的是 MySQL 服务器当前的系统时间(精确到秒,含微秒可加参数),**不是客户端时间,也不是 UTC 时间**。时区由服务器的 time_zone 系统变量决定,默认通常是系统时区(如 SYSTEM),不是 UTC。
- 执行
SELECT NOW();得到的时间,和你在服务器上跑date命令看到的几乎一致 - 如果服务器时区是
Asia/Shanghai,NOW()就返回东八区时间;设成+00:00,就返回 UTC - 别想当然认为它“自动适配本地浏览器时区”——数据库没这功能,纯看服务端配置
NOW() 和 CURRENT_TIMESTAMP() 有区别吗?
在绝大多数场景下,完全等价,都是同义词,都受 time_zone 控制,都支持微秒精度(如 NOW(3) 返回毫秒级)。但要注意:
- 作为列默认值时,
CURRENT_TIMESTAMP可以带括号写成CURRENT_TIMESTAMP(),而NOW()在旧版本(5.6 以前)某些上下文中可能不被允许作默认值(虽现在基本无差别) - SQL 标准更倾向用
CURRENT_TIMESTAMP,所以建表时若追求可移植性,优先选它 - 二者都不接受参数传入自定义时间——想插固定时间就得写死字符串,比如
'2024-05-20 10:30:00'
插入数据时用 NOW() 还是提前在应用层生成时间?
取决于你对「时间源头」和「一致性」的要求。直接在 SQL 里用 NOW() 更简单,但也埋了坑:
- 多个字段同时用
NOW()(比如created_at和updated_at),能保证它们严格一致(同一毫秒);如果应用层生成再拼 SQL,网络延迟或时钟漂移可能导致微小偏差 - 但如果业务逻辑需要「创建时间 = 某个事件发生时刻」,而该事件在应用层判定(比如支付成功回调),那必须由应用层传入,否则数据库不知道那个“事件点”
- 跨服务写入时,各服务机器时钟不同步会导致
NOW()结果不一致——这时建议统一用应用层生成 + 传入UTC时间戳,再转存为DATETIME
为什么 NOW() 插进去的时间比你预期早/晚 8 小时?
几乎全是时区配置问题。检查三处:
- 查服务器当前设置:
SELECT @@global.time_zone, @@session.time_zone;。常见错误是全局为SYSTEM,但系统时区其实是UTC(Docker 容器、某些云 RDS 默认如此) - 连接时没指定时区:PHP 的
mysqli或 Python 的pymysql需显式加init_command='SET time_zone = "+08:00"',否则会沿用服务器默认,可能和你的预期不符 -
DATETIME类型本身不存时区信息,它只是“字面时间”。你用NOW()插了个2024-05-20 14:00:00,它就永远显示这个字符串——改服务器时区也不会变,这点和TIMESTAMP本质不同
time_zone 配置,NOW() 就成了黑盒。










