本文阅读时间大约6分钟。

写在前面

最近工作中遇到两例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的精度和查询参数的精度等问题。

参考资料

  1. https://dev.mysql.com/doc/refman/8.0/en/datetime.html

  2. 《高性能MySQL》

热门内容:   

  

  • 如何优雅的导出 Excel

  • JDK 13 新特性一览

  • 某小公司RESTful、共用接口、前后端分离、接口约定的实践

  • 请停止学习框架

  • IntelliJ IDEA 2019.3这回真的要飞起来了,新特性抢先看!

  • 想不到!面试官问我:Redis 内存满了怎么办?

  • 用了这么久 IDEA,你竟然不知道有个功能叫自动补全!

  • 5 门可能衰落的编程语言

  • 优秀的 Java 项目代码都是如何分层的?

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

一次 Jar 包升级引发的血案 amp; 解决相关推荐

  1. Jar 包依赖冲突排查思路和解决方法(logback + slf4j-log4j12)

    Jar 包依赖冲突排查思路和解决方法 [TOC] 起因 喜大普奔,本期发布中,我们的应用从 jdk7 升级到 jdk8,终于可以用上新特性的语法进行代码编写,通过几轮开发.测试和验证后,在上预发环境时 ...

  2. Log4j2 日志 依赖 jar包 缺失 导致启动报错 解决方法

    Log4j2 日志 依赖 jar包 缺失 导致启动报错 解决方法. 一个Java老项目,更新了日志工具,升级为Log4j2,在引入log4j-api-2.14.0.jar 和log4j-core-2. ...

  3. POI版本对比jar包升级后代码报错修正

    学习目标: 最近使用EasyExcel写导入导出Excel,需要POI版本是3.17,之前是3.9,必须升级jar包,升级之后发现很多代码报错,需要修改调整,以下用于记录调整的代码. 颜色定义变化 旧 ...

  4. jar包升级部署到服务器详细流程,将服务部署在linux中

    假设你已经准备好以下东西,即可进行服务部署 一台服务器(云服务器或虚拟机皆可) 已安装好的jdk 1.8 + 的环境(可自行百度) 打好的jar包(maven打jar包) 1. 在服务器中新建好你的项 ...

  5. Jar 包依赖冲突排查思路和解决方法

    作者:jingQ https://www.sevenyuan.cn/ 起因 应用从 jdk7 升级到 jdk8,终于可以用上新特性的语法进行代码编写,通过几轮开发.测试和验证后,在上预发环境时,应用突 ...

  6. maven jar包冲突常见报错及解决方法

    见到如下错误,可以想到是不是jar包冲突 1.java.lang.NoSuchMethodError 2.java.lang.ClassNotFoundException 3.java.lang.No ...

  7. was服务器里面jar包_如何在was中解决jar包冲突

    如何在 was 中解决 jar 包冲突 大型的基于 WebSphere 的项目开发中,同一个 WebSphere Application Server (以下 简称 WAS ) 上会部署多个应用程序, ...

  8. android 混淆不混淆第三方jar,Android 第三方Jar包FastJson 代码混淆时的解决方法 - Android开发论坛 - 51CTO技术论坛_中国领先的IT技术社区...

    我们做AndroidApp软件的时候,经常会对App进行签名打包和代码混淆,在工程中没有使用第三方Jar文件的时候不用考虑很多因素,现在要说的是当你在你的工程使用使用了FastJson这个快速解析Js ...

  9. java win10窗口启动假死_window执行jar包会出现假死现象解决

    windows jar包启动的几种方式介绍 java -jar xxx.jar(jar包的路径),最普通简单的方式,通过windows的命令行窗口启动,并在命令行窗口运行,输出.可以在启动的时候增加参 ...

最新文章

  1. 【java基础】map的基本使用与字符串中每个字符出现的次数统计
  2. Java Servlet 开发常用代码、模板、问题
  3. [Python图像处理] 三十六.OpenCV图像几何变换万字详解(平移缩放旋转、镜像仿射透视)
  4. 第七章:项目成本管理
  5. mysql的中文乱码url,MySQL 中文显示乱码
  6. python time智能等待_Python Selenium智能等待
  7. java中bash应用_在bash脚本中查找java应用程序的进程ID(以查看目标应用程序是否已在运行)...
  8. HttpClient4.3.x的连接管理
  9. 史上最详细的JNI入门教程HelloNative
  10. Delaunay三角剖分算法
  11. 在Flex4中嵌入字体
  12. countifs函数怎么用,excel函数的操作步骤
  13. 记一次quartz定时任务不执行排雷
  14. windows的文件路径文件(夹)名的分割符也可以用正斜杠
  15. ADO 从ACCESS数据库读取图片并显示出来
  16. 微型计算机基础学的什么,微型计算机操作基础课的教学
  17. ad被锁定的账户_如何在AD中方便查询被锁定的帐号状态和特定条件的查询被锁定的帐号...
  18. 3.2 使用直线段工具标注尺寸信息 [Illustrator CC教程]
  19. matlab 拉布拉斯矩阵,关于图像处理:C ++中的拉普拉斯矩阵计算
  20. 图文细说11种计算机图标符号的历史

热门文章

  1. python 将字符串转换成字典dict
  2. [luoguP2618] 数字工程(DP)
  3. ApacheBench(ab)使用详解
  4. js markdown chart flow
  5. 异步发送邮件、短信、微信
  6. bzoj1562[NOI2009]变换序列——2016——3——12
  7. C#中静态方法的运用和字符串的常用方法(seventh day)
  8. BroadcastReceiver自学笔记
  9. 2021 线性代数 第五章 习题课
  10. 快速滚动_方老师教滚动快速作文