NOW() 返回 MySQL 服务器本地时间,与客户端时区无关;其等价于 CURRENT_TIMESTAMP(),返回带秒精度的 DATETIME 值;需通过 SET time_zone 或配置 default-time-zone 调整时区;跨时区场景应优先使用 UTC_TIMESTAMP()。

NOW() 返回的是服务器本地时间,不是客户端时间
调用 NOW() 时,数据库会直接读取运行 MySQL 服务的操作系统当前时间,和你执行查询的设备(浏览器、命令行、应用服务器)所在时区无关。如果你的应用部署在 UTC 服务器,但业务面向中国用户,NOW() 返回的就是 UTC 时间,不是 Asia/Shanghai 时间。
常见错误现象:前端显示“2024-05-20 14:30:00”,但数据库里用 NOW() 插入后查出来是 “2024-05-20 06:30:00”——大概率是服务器时区设成了 UTC,而你误以为它自动适配了本地时区。
- 检查当前 MySQL 服务器时区:
SELECT @@global.time_zone, @@session.time_zone; - 临时切换会话时区(仅当前连接生效):
SET time_zone = '+8:00';或SET time_zone = 'Asia/Shanghai'; - 永久修改需调整 MySQL 配置文件中的
default-time-zone,并重启服务
NOW() 和 CURRENT_TIMESTAMP() 完全等价,但不能带参数
在 MySQL 中,NOW() 是 CURRENT_TIMESTAMP() 的同义词,两者行为完全一致,都返回带秒精度的 DATETIME 值(如 2024-05-20 15:22:37)。注意它不接受任何参数,NOW(3) 或 NOW(6) 在 MySQL 8.0.22+ 才支持微秒精度,且必须显式写成 NOW(3) 形式;老版本直接报错 FUNCTION NOW does not exist。
使用场景:适合记录创建时间、日志打点、条件过滤“最近一小时的数据”等。
- 插入记录时自动填充时间:
INSERT INTO logs (msg, created_at) VALUES ('task started', NOW()); - 查询最近 5 分钟数据:
WHERE updated_at >= NOW() - INTERVAL 5 MINUTE - 不要写
NOW()加括号又不传参还加空格,如NOW ()—— MySQL 会报语法错误
如果需要 UTC 时间,别用 NOW(),改用 UTC_TIMESTAMP()
NOW() 绑定服务器时区,UTC_TIMESTAMP() 则始终返回协调世界时,不受 time_zone 设置影响。当你的系统跨时区部署、或需要统一时间基准(比如分布式任务调度、审计日志),硬编码依赖 NOW() 容易引发时间错乱。
性能与兼容性影响:两者底层开销几乎相同,但 UTC_TIMESTAMP() 更利于后期迁移和时区解耦。某些 ORM(如 Laravel 的 Eloquent)默认用 NOW()),若未同步配置时区,会导致模型时间字段偏差。
- 插入 UTC 时间:
INSERT INTO events (name, at_utc) VALUES ('deploy', UTC_TIMESTAMP()); - 对比两种时间:
SELECT NOW(), UTC_TIMESTAMP();(差值即为服务器本地偏移) - 注意:PostgreSQL 没有
NOW()函数,对应的是NOW()(它本身返回的是 timestamptz),别混淆
在 INSERT ... ON DUPLICATE KEY UPDATE 中,NOW() 每次都会重新求值
这是容易被忽略的行为:当语句触发了重复键更新分支,NOW() 不会复用插入时的值,而是再次执行一次,导致 created_at 和 updated_at 可能相差几毫秒甚至更多(尤其在高并发下)。如果你希望“首次插入用 NOW(),更新时也用同一个时间”,就不能直接写两次 NOW()。
正确做法是用变量暂存,或改用 VALUES(col_name) 引用原插入值。
- 安全写法(推荐):
INSERT INTO t (id, ts) VALUES (1, NOW()) ON DUPLICATE KEY UPDATE ts = VALUES(ts); - 手动控制:
SET @now := NOW(); INSERT INTO t VALUES (1, @now) ON DUPLICATE KEY UPDATE ts = @now; - 错误写法:
... ON DUPLICATE KEY UPDATE ts = NOW()→ 更新时间会比插入时间略晚
MySQL 的 NOW() 看似简单,但时区、精度、上下文重求值这三点,实际线上出问题最多。尤其是微服务拆分后各组件数据库实例时区不一致,或者从自建库迁移到云 RDS(默认 UTC)时,NOW() 的行为差异会直接暴露逻辑缺陷。


















