百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一个时间戳精度问题,引发了一个MySQL血案

haoteby 2025-02-08 11:07 41 浏览

文章来源:https://dwz.cn/ajsWJTWv

作者:阿杜的世界

最近工作中遇到两例mysql时间戳相关的问题,一个是mysql-connector-java和msyql的精度不一致导致数据查不到;另一例是应用服务器时区错误导致数据查询不到。

通过这篇文章,希望能够解答关于mysql中时间戳的几个问题:

  1. mysql中的DATETIME精度为什么只支持到秒?
  2. mysql中的DATETIME类型跟时区有关吗?
  3. mysql设计表的时候,表示时间的字段改如何选择?

案例分析:DATETIME的精度问题

前段时间,将负责的应用的mysql-connector-java的版本从5.1.16升级到5.1.30,在做功能回归的时候发现,使用了类似上面的SQL的用例的运行时数据会有遗漏,导致功能有问题。

考虑到我负责的应用中,有个功能需要用到类似下面这种SQL,即使用时间戳作为查询的条件,查询在某个时间戳之后的所有数据。

经过排查发现:mysql-connector-java在5.1.23之前会将秒后面的精度丢弃再传给MySQL服务端,正好我们使用的mysql版本中DATETIME的精度是秒;在我将mysql-connector-java升级到5.1.30后,从java应用通过mysql-connector-java将时间戳传到MySQL服务端的时候,就不会将毫秒数丢弃了,从mysql-connector-java的角度看是修复了一个BUG,但是对于我的应用来说却是触发了一个BUG。

如果你面对这个问题,你会怎么修复呢?

我们当时想了三种方案:

  • 将mybatis的Mapper接口中的时间戳参数的类型,从java.util.Date改成java.sql.Date;
  • 在传入Mapper接口之前,将传入的时间戳按秒取正,代码如下
  • 在查询之前,将传入的时间戳减1秒;
  • 经过验证,方案1会,java.util.Date转过去的java.sql.Date对象会将日期之后的精度全部丢掉,从而导致查询出更多不必要的数据;方案3是可以的,就是可能会查出多一两条数据;方案2也是可以的,相当于从代码上对mysql-connector-java的特性做了补偿。最终我选择的是方案2。

    案例复现

    利用homebrew安装MySQL,版本是8.0.15,装好后建一个表,用来存放用户信息,SQL如下:

    使用spirngboot + mybatis作为开发框架,定义一个用户实体,代码如下所示:

    定义该实体对应的Mapper,代码如下:

    设置连接mysql相关的配置,代码如下:

    编写测试代码,先插入一条数据,然后用时间戳作为查询条件去查询,代码如下:

    运行单测,如我们的设想,确实是没有查询出数据来,结果如下:

    然后修改代码,利用上面的代码将查询的时间戳按秒取正,代码如下:

    再次运行单测,如我们的设想,这次可以查询出数据来了。

    不过,这里有个小插曲,我在最开始设计表的时候,使用的SQL语句是下面这样的:

    你一定发现了,这里的datetime已经支持小数点后更小的时间精度了,最多支持6位即最多可以支持到微妙级别。这个特性是什么时候引入的呢,我去查阅了MySQL的官方文档(
    https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html),发现这个特性是在mysql 5.6.4之后开始支持的。

    知识点总结

    经过了前面的实际案例分析和案例复现,想必读者已经对mysql中DATETIME这个类型有了一定的认识,接下来跟我一起看下,我们从这个案例中可以总结出哪些经验。

    1.mysql-connector-java的版本和mysql的版本需要配套使用,例如5.6.4之前的版本,就最好不要使用mysql-connector-java的5.1.23之后的版本,否则就可能会遇到我们这次遇到的问题。

    2.MySQL中用来表示时间的字段类型有:DATE、DATETIME、TIMESTAMP,它们之间有相同点,各自也有自己的特性,我总结了一个表格,如下所示:

    3.DATETIME类型在MySQL中是以“YYYYMMDDHHMMSS”格式的整数存放的,与时区无关,使用8个字节的空间;

    4.TIMESTAMP类型可以保存的时间范围要小很多,显示的值依赖时区,MySQL的服务器、操作系统以及客户端连接都有时区的设置。

    5.一般情况下推荐使用DATETIME作为时间戳字段,不推荐使用bigint类型来存储时间。

    6.在开发中,应该尽量避免使用时间戳作为查询条件,如果必须要用,则需要充分考虑MySQL的精度和查询参数的精度等问题。

    相关推荐

    如何随时清理浏览器缓存_清理浏览器缓存怎么弄

    想随时清理浏览器缓存吗?Cookieformac版是Macos上一款浏览器缓存清理工具,所有的浏览器Cookie,本地存储数据,HTML5数据库,FlashCookie,Silverlight,...

    Luminati代理动态IP教程指南配置代理VMLogin中文版反指纹浏览器

    介绍如何使用在VMLogin中文版设置Luminati代理。首先下载VMLogin中文版反指纹浏览器(https://cn.vmlogin.com)对于刚接触Luminati动态ip的朋友,是不是不懂...

    mac清除工具分享,解除您在安全方面的后顾之忧

    想要永久的安全的处理掉重要数据,删除是之一,使用今天小编分享的mac清除工具,为您的操作再增一层“保护”,小伙伴慎用哟,一旦使用就不可以恢复咯,来吧一起看看吧~mac清除工具分享,解除您在安全方面的后...

    取代cookie的网站追踪技术:”帆布指纹识别”

    【前言】一般情况下,网站或者广告联盟都会非常想要一种技术方式可以在网络上精确定位到每一个个体,这样可以通过收集这些个体的数据,通过分析后更加精准的去推送广告(精准化营销)或其他有针对性的一些活动。Co...

    辅助上网为啥会被抛弃 曲奇(Cookie)虽甜但有毒

    近期有个小新闻,大概很多小伙伴都没有注意到,那就是谷歌Chrome浏览器要弃用Cookie了!说到Cookie功能,很多小伙伴大概觉得不怎么熟悉,有可能还不如前一段时间被弃用的Flash“出名”,但它...

    浏览器指纹是什么?浏览器指纹包括哪些信息

    本文关键词:浏览器指纹、指纹浏览器、浏览器指纹信息、指纹浏览器原理什么是浏览器指纹?浏览器指纹是指浏览器的各种信息,当我们访问其他网站时,即使是在匿名的模式下,这些信息也可以帮助网站识别我们的身份。...

    那些通用清除软件不曾注意的秘密_清理不常用的应用软件

    系统清理就像卫生检查前的大扫除,即使你使出吃奶的劲儿把一切可能的地方都打扫过,还会留下边边角角的遗漏。随着大家电脑安全意识的提高,越来越多的朋友开始关注自己的电脑安全,也知道安装360系列软件来"武装...

    「网络安全宣传周」这些安全上网小知识你要知道!

    小布说:互联网改变了人们的衣食住行,但与之伴生的网络安全威胁也不容忽视。近些年来,风靡全球的勒索病毒、时有发生的电信诈骗、防不胜防的个人信息泄露时时刻刻都威胁着我们的生活。9月18日-24日是第四届...

    TypeScript 终极初学者指南_typescript 进阶

    在过去的几年里TypeScript变得越来越流行,现在许多工作都要求开发人员了解TypeScript...

    jQuery知识一览_jquery的认识和使用

    一、概览jQuery官网:https://jquery.com/jQuery是一个高效、轻量并且功能丰富的js库。核心在于查询query。...

    我的第一个Electron应用_electronmy

    hello,好久不见,最近笔者花了几天时间入门Electron,然后做了一个非常简单的应用,本文就来给各位分享一下过程,Electron大佬请随意~笔者开源了一个Web思维导图,虽然借助showSav...

    HTML5 之拖放(Drag 和 Drop)_html拖放api

    简介拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在HTML5中,拖放是标准的一部分,任何元素都能够拖放。先点击一个小例子:在用户开始拖动<p>元素时执行JavaScrip...

    如何用JavaScript判断输入值是数字还是字母?

    在日常开发中,我们有时候需要判断用户输入的是数字还是字母。本文将介绍如何用JavaScript实现这一功能。检查输入值是否是数字或字母...

    图形编辑器开发:快捷键的管理_图形编辑工具

    大家好,我是前端西瓜哥。...

    浏览器原生剪贴板:原来它能这样读取用户截图!

    当我们使用GitHub时,会发现Ctrl+V就能直接读取用户剪贴板图片进行粘贴,那么它是如何工作的?安全性如何?...