You need to enable JavaScript to run this app. 如何避免MySQL timestamp四舍五入及Liquibase修改timestamp(3)报错问题
优惠活动
大模型
产品
解决方案
定价
更多

如何避免MySQL timestamp四舍五入及Liquibase修改timestamp(3)报错问题

问题原因

  • MySQL 对带精度的TIMESTAMP类型有严格的默认值匹配规则:原有updated_at字段设置了无精度的默认值(比如默认的CURRENT_TIMESTAMP、'0000-00-00 00:00:00'),直接修改字段类型为timestamp(3)时,旧默认值和新类型的精度要求不兼容,因此触发1067错误。
  • 你的修改逻辑本身是对的,timestamp(3)确实可以存储毫秒级时间,避免后端传入的毫秒部分被四舍五入,问题出在变更操作没有处理原有默认值的兼容问题。

修复方案

1. 调整Liquibase变更脚本

分三步执行变更:先移除原有默认值,再修改字段类型,最后按需重新设置带精度的默认值,示例脚本如下:

<changeSet id="10" author="autho2">
    <!-- 第一步:移除字段原有默认值约束 -->
    <dropDefaultValue tableName="user_data" columnName="updated_at"/>
    <!-- 第二步:修改字段为带3位毫秒精度的TIMESTAMP -->
    <modifyDataType
            columnName="updated_at"
            newDataType="timestamp(3)"
            tableName="user_data"/>
    <!-- 第三步:如果需要保留默认值,重新设置带精度的默认值,不需要可删除此步 -->
    <addDefaultValue 
            tableName="user_data" 
            columnName="updated_at"
            defaultValueComputed="CURRENT_TIMESTAMP(3)"/>
</changeSet>

如果你的字段原本不允许为NULL,可根据业务需求在modifyDataType时补充NULL/NOT NULL声明。

2. 适配实体类定义

为了保证JPA层面和数据库类型匹配,建议补充@Column的精度声明:

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_at", columnDefinition = "timestamp(3)")
private Date updatedAt;

如果使用JDK 8及以上版本,替换java.util.Date为java.time.Instant/java.time.LocalDateTime可以避免时区和精度序列化的额外问题,无需再加@Temporal注解。

3. 验证效果

变更执行完成后,传入2021-08-11T21:59:59.999Z即可完整存储毫秒部分,不会再被四舍五入为下一分钟。

内容的提问来源于stack exchange,提问作者Catalina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 00:30:00