当前位置: 首页 > news >正文

MySQL DATETIME 类型时间精度陷阱:一次由毫秒引发的数据“消失”之谜

本文提及MySQL 版本均指 5.7.26,涉及表、列值名称均为伪代码,场景是生产环境真实产生的问题,在此记录、分享。

💗💗💗您的点赞、收藏、评论是博主输出优质文章的的动力!!!💗💗💗

欢迎在评论区与博主沟通交流!!大量优质博文关注一波不亏!👇🏻 👇🏻 👇🏻

文章目录

  • MySQL DATETIME 类型时间精度陷阱:一次由毫秒引发的数据“消失”之谜
    • 问题现象:数据明明存在却查询不到
    • 排查过程:抽丝剥茧的真相追踪
      • 第一阶段:基础排查(预期30分钟,实际5分钟)
      • 第二阶段:深度对比分析(关键突破点)
    • 根因分析:MySQL的时间精度陷阱
      • DATETIME类型的存储真相
      • 为什么应用层会出现精度不一致?
    • 解决方案
      • 快速止血
      • 一些其他想法(未实施)
    • 总结
    • 反思:从“BUG”到“架构优化”的启示

MySQL DATETIME 类型时间精度陷阱:一次由毫秒引发的数据“消失”之谜

问题现象:数据明明存在却查询不到

我们遇到了一个诡异现象,数据库中存在数据,但是生产环境执行查询时,日志输出返回为null,经过核对在Table1表中,确认存在一条记录:

column1 = 'xxxxxx' 
column2 = '2025-06-25 09:01:54' 
column3 = 1 
column4 = 0

但当执行以下查询时却返回空结果:

SELECT * FROM Table1
WHERE ( column1 = 'xxxxxx' AND column2 = '2025-06-25 09:01:54.999' AND column3 = 1 AND column4 = 0 
)

排查过程:抽丝剥茧的真相追踪

第一阶段:基础排查(预期30分钟,实际5分钟)

  1. 数据存在性验证

    -- 使用精确值查询
    SELECT * FROM Table1
    WHERE column1 = 'xxxxxx' AND column2 = '2025-06-25 09:01:54' AND column3 = 1 AND column4 = 0;
    

    确认数据存在且符合条件

  2. SQL语法检查

    • WHERE条件逻辑正确
    • 字段名拼写无误
    • 表名正确

第二阶段:深度对比分析(关键突破点)

通过 EXPLAIN 和查询日志对比两种SQL:

-- 有效查询
EXPLAIN SELECT ... WHERE column2 = '2025-06-25 09:01:54'-- 失效查询
EXPLAIN SELECT ... WHERE column2 = '2025-06-25 09:01:54.999'

发现执行计划相同,都使用了索引,但结果不同。此时聚焦到时间字段的精度差异

查询条件值实际存储值是否匹配
2025-06-25 09:01:54.9992025-06-25 09:01:54.000000
2025-06-25 09:01:542025-06-25 09:01:54.000000

根因分析:MySQL的时间精度陷阱

DATETIME类型的存储真相

MySQL的 DATETIME 类型在5.6版本后支持微秒级精度,但精度定义在表结构中

-- 查看表结构
SHOW CREATE TABLE Table1;-- 输出关键信息
`column2` DATETIME NOT NULL  -- 未指定精度,默认为0

这意味着:

  1. 插入2025-06-25 09:01:54.999会被隐式截断2025-06-25 09:01:54这里其实存在另外一个问题,MySQL会自动转换,对毫秒位进行四舍五入,我会在下一篇博客中介绍
  2. 查询时不会自动转换:'2025-06-25 09:01:54' ≠ '2025-06-25 09:01:54.999'

为什么应用层会出现精度不一致?

追查代码,发现问题是因为查询时 column2 字段类型是 java.util.Date,组装查询对象时,方法签名对象中的参数是 java.lang.Long,所以转换时出现了时间精度的问题,伪代码如下所示:

// 这里的timestampL是精确到毫秒级,雷炸了..
public void test(Long timestampL){Table1Entity t = new Table1Entity();t.setColumn2(new Date(timestampL));Table1Entity rT = queryOne(t);LOG.info("rt input:{}, output:{}", JsonUtils.toJson(t), JsonUtils.toJson(rT));  
}

当从其他微服务获取时间数据时,新的序列化格式引入了毫秒信息。

解决方案

快速止血

这里的快速止血可能不是最好方案,只是为了解决出现问题的业务场景;

我们这里直接修改 Table1Entity.java 类中的 column2 属性的set方法,直接把属性的时间毫秒位置成0;

考虑到此场景在写库 column2 值时,就已经把毫秒位给截断掉了,所以直接在应用层也同步做此操作;

 public void setColumn2(Date column2) {if (Objects.nonNull(column2)) {Calendar calendar = Calendar.getInstance();calendar.setTime(column2);calendar.set(Calendar.MILLISECOND, 0);this.column2 = calendar.getTime();} else {this.column2 = stayStartTime;}}

一些其他想法(未实施)

数据库层优化(中长期方案)

-- 方案1:明确定义精度(需业务停写)
ALTER TABLE Table1 
MODIFY column2 DATETIME(3); -- 精确到毫秒-- 方案2:使用时间范围查询(兼容现有精度)
SELECT * FROM Table1 
WHERE column1 = 'xxxxxx'AND column2 >= '2025-06-25 09:01:54' AND column2 < '2025-06-25 09:01:55'AND column3 = 1 AND column4 = 0

总结

在系统详设阶段,应该注意涉及时间相关的存储与查询精度需要保持一致:

  • 创建表时显式定义精度:DATETIME(3) vs DATETIME(0)
  • 全链路统一精度处理

反思:从“BUG”到“架构优化”的启示

这次事故表面是时间精度问题,实则是系统边界一致性的典型案例。在微服务架构中,我们应:

  1. 建立明确的数据类型契约(如Protobuf定义时间精度)
  2. 在API网关层进行数据清洗
  3. 对核心字段添加变更熔断机制

“魔鬼藏在细节中——在时间处理领域,1毫秒的误差可能导致整个业务逻辑的崩塌。精确的时间管理不仅是技术需求,更是业务连续性的保障。”

通过这次复盘,我们不仅修复了一个查询BUG,更重要的是建立了全链路时间精度管控体系,为系统的高可靠性奠定了坚实基础。


感 谢 各 位 大 佬 的 阅 读,随 手 点 赞,日 薪 过 万~! !!
http://www.lqws.cn/news/580213.html

相关文章:

  • 计算机网络第一章——计算机网络体系结构
  • Pandas5(数据清洗1)——缺失值处理、数据去重/转换/替换、离散化/分箱、检测和过滤异常值
  • 【Kafka】docker 中配置带 Kerberos 认证的 Kafka 环境(全过程)
  • NIO 工作原理
  • C++ cstring 库解析:C 风格字符串函数
  • 【甲方安全建设】SDL基线建设及审计评估
  • API接口安全-2:签名、时间戳与Token如何联手抵御攻击
  • 【第二章:机器学习与神经网络概述】04.回归算法理论与实践 -(1)线性回归模型
  • Web攻防-SSRF服务端伪造功能逻辑SRC实践复盘参数盲测自动化检测流量插件
  • 【ArcGISPro】解决Pro不能导入AppData下的site-packages
  • MySQL数据库--SQL DDL语句
  • 大学专业科普 | 云计算、大数据
  • 淘宝API接口在数据分析中的应用
  • [springboot系列] 探秘 JUnit 5:现代 Java 单元测试利器
  • 2025年数据治理平台排名及功能对比分析
  • Nacos 3.0 架构全景解读,AI 时代服务注册中心的演进
  • 通过案列理解js中的深拷贝和浅拷贝
  • Server-Sent Events (SSE) 技术详解
  • 【原创】【5】【视频二创工具发布】基于视觉模型+FFmpeg+MoviePy实现短视频自动化二次编辑+多赛道
  • Windows 开发环境部署指南:WSL、Docker Desktop、Podman Desktop 部署顺序与存储路径迁移指南
  • PreparedStatement详解
  • Vue3静态文档资源展示的实现和使用总结
  • 【CS创世SD NAND征文】SD NAND赋能新一代儿童智能玩具
  • js代码04
  • 生信分析之流式数据分析:Flowjo 软件核心功能全解析
  • 《微信生态裂变增长利器:推客小程序架构设计与商业落地》
  • 颠覆传统加密:微算法科技创新LSQb算法,提升量子图像处理速度
  • python | numpy小记(四):理解 NumPy 中的 `np.round`:银行家舍入策略
  • BUUCTF在线评测-练习场-WebCTF习题[MRCTF2020]你传你[特殊字符]呢1-flag获取、解析
  • 攻防世界-MISC-red_green