NOW()在事务中时间不变,因其在事务首条语句执行时固定时间戳;SYSDATE()每次调用实时读取系统时钟;建表默认值须用CURRENT_TIMESTAMP而非NOW();时区切换不影响事务内NOW()一致性。

同一个事务里多次调用NOW()为什么时间不变
因为NOW()在事务开始执行第一条语句时就“拍下快照”,后续所有调用都复用这个时间点,不是实时读取系统时钟。这是 MySQL 为保证事务内时间一致性做的强制行为。
NOW()和SYSDATE()在事务中表现差异明显
两者底层机制不同:NOW()绑定语句起始时刻,SYSDATE()每次调用都触发一次系统时钟读取。这导致:
- 在长事务或含
SLEEP()的测试中,SELECT NOW(), SLEEP(2), NOW()返回两个相同值 - 而
SELECT SYSDATE(), SLEEP(2), SYSDATE()两次结果相差约 2 秒 - UPDATE 多行时,
SET created_at = NOW()让所有行获得同一时间戳;换成SYSDATE()则可能产生毫秒级偏差
建表时设默认值必须用CURRENT_TIMESTAMP,不能用NOW()
语法限制:MySQL 明确不接受DEFAULT NOW(),会报错ERROR 1064。原因在于建表语句解析阶段只允许标准 SQL 时间字面量函数,而NOW()被归类为运行时表达式。
- 正确写法:
created_at DATETIME DEFAULT CURRENT_TIMESTAMP - 支持精度:
CURRENT_TIMESTAMP(3)(毫秒)或CURRENT_TIMESTAMP(6)(微秒),需字段类型匹配(如DATETIME(3)) -
NOW(3)在INSERT中可用,但无法用于DDL定义默认值
时区设置会影响NOW()结果,但不会改变“事务内一致”这一行为
无论time_zone设成'+08:00'还是UTC,只要在同一个事务里,NOW()始终返回该事务启动时刻对应时区下的固定值。
- 查当前会话时区:
SELECT @@time_zone - 临时切换:
SET time_zone = '+08:00',之后的NOW()立即按新时区计算,但事务内仍锁定初始值 - 注意:
TIMESTAMP类型字段受时区影响更大——存入和读出都会转换;DATETIME则完全无视时区,只忠于字面值
NOW()做步骤计时,得到的其实是“步骤开始时间”,而非“每个步骤实际发生的时间”。需要逐次打点,得换SYSDATE()或客户端时间。


















