now() 返回会话时区下的当前日期时间,非绝对时间;与 current_timestamp() 完全同义;支持毫秒精度需指定如 now(3);写入 timestamp 比 datetime 更适合跨时区统一基准。

NOW() 在 MySQL 中直接返回当前日期和时间,精确到秒(默认不带毫秒),但它的行为受会话时区影响,不是“绝对当前时间”的银弹。
为什么 NOW() 有时看起来不准?
它返回的是 MySQL 服务器当前会话的 TIMESTAMP 值,依赖于 time_zone 系统变量。如果会话时区被显式设为 '+00:00' 或 'SYSTEM',结果可能和你本地感知的时间不一致。
- 检查当前会话时区:
SELECT @@session.time_zone; - 临时切换为系统时区:
SET time_zone = 'SYSTEM'; - 想强制用 UTC:
SET time_zone = '+00:00';,再调用NOW()
NOW() 和 CURRENT_TIMESTAMP() 有区别吗?
没有实质区别——二者完全同义,都是 SQL 标准函数,在 MySQL 中互换使用不会有任何行为差异。但注意:CURDATE() 只返回日期部分('2024-05-20'),CURTIME() 只返回时间部分('14:30:22')。
- 建表时用作默认值,两者都合法:
created_at DATETIME DEFAULT NOW() - 触发器中建议统一用
NOW(),语义更直白 - 避免混用
NOW()和SYSDATE():后者在语句执行过程中可能变化(如在存储过程中多次调用),而NOW()在语句开始时就固定了
需要毫秒精度怎么办?
NOW() 默认不带小数秒,但 MySQL 5.6.4+ 支持微秒精度,只需显式指定精度:
-
NOW(3)→ 返回类似'2024-05-20 14:30:22.123' -
NOW(6)→ 最高支持 6 位微秒,但实际精度还取决于系统时钟和存储引擎(如 InnoDB 对DATETIME(6)的支持是完整的) - 字段定义也要匹配:
created_at DATETIME(3) DEFAULT NOW(3)
在 INSERT 或 UPDATE 中直接用 NOW() 安全吗?
安全,但要注意隐式类型转换风险。例如把 NOW() 插入 DATE 字段,MySQL 会自动截断时间部分;插入 TIMESTAMP 字段则会按当前时区转换为 UTC 存储。
-
TIMESTAMP列存的是 UTC,读取时再转回会话时区 —— 这意味着跨时区应用里,NOW()写入TIMESTAMP比写入DATETIME更可靠 - 如果字段是
DATETIME,且业务逻辑依赖“原始服务器时间”,那就用NOW();如果依赖“统一时间基准”,优先选TIMESTAMP+NOW() - 不要在 WHERE 条件中对
NOW()做函数运算(如WHERE DATE(NOW()) = DATE(created_at)),会阻止索引使用
真正容易被忽略的是时区上下文和字段类型的隐式配合——NOW() 本身很简单,但一嵌进表结构、复制环境或跨时区服务里,错的往往不是函数,而是没确认好 time_zone 和列类型的组合行为。










