MySQL时区造成时差问题


Posted in MySQL onApril 13, 2022

前言

今天来聊一个简单的话题,这是一个小伙伴在微信上问我的,对于初学者我非常能理解这类问题带来的困扰,各种尝试,各种搜索,别人说的头头是道,但是就是解决不了自己的问题,今天我简单从两个方面来和大家聊聊这个问题,如果小伙伴们有其他的解决思路,也可以留言一起分享。

这个问题我们可以从两方面来分析:

  • MySQL 本身的问题。
  • Java 代码的问题。

1. MySQL 本身问题

MySQL 本身问题,这个其实很好验证,不就是时间么,我们执行如下 SQL 看看 MySQL 上的时间跟我的电脑时间是否是一致的:

select now();

MySQL时区造成时差问题

可以看到,MySQL 的这个时间跟我系统的时间其实就差了 8 小时,MySQL 本身的时间都不对,那你将来插入/查询的时间肯定也不对。

这个查询大家注意,要么使用命令行操作,要么使用 Sqlyog、Navicat 或者 Sequel Pro 之类的数据库工具来操作,切勿使用 JDBC 来查询,具体原因一会看完第二小节就明白了。

出现这个问题,多半是 MySQL 的时区不太对,我们重新给其设置一下时区即可。

首先我们通过如下指令来查看一下 MySQL 当前的时区:

show variables like '%time_zone%';

MySQL时区造成时差问题

可以看到,MySQL 说它的时区是 SYSTEM,那 SYSTEM 又是啥呢?第一条说了 SYSTEM 是 UTC(协调世界时,又称世界标准时间或世界协调时间)。而我们的北京时间比 UTC 快了 8 小时,即 UTC+8。

所以我们现在要把 MySQL 的时区先给改对,可以通过修改配置文件来实现(/etc/mysql/mysql.conf.d/mysqld.cnf),如下:

MySQL时区造成时差问题

修改完成后,重启 MySQL,再来查看 MySQL 的时区:

MySQL时区造成时差问题

可以看到,此时的 MySQL 时区就正常了。

那么此时再执行 select now(); 也就不会有问题了:

MySQL时区造成时差问题

有的小伙伴可能嫌修改配置文件太麻烦了,那么也可以通过 SQL 来修改时区:

set global time_zone = Asia/Shanghai

注意我们所在的时区是 Asia/Shanghai,小伙伴们不要自由发挥写其他城市。

首先我们要确认 MySQL 没问题。

2. JDBC 连接问题

当确认了 MySQL 没有问题后,如果你的 MySQL 时间还是不对,那么就有可能是 JDBC 连接的问题了。

这里我用大家常见的 JdbcTemplate 来举个例子,其他的数据库框架操作也都是一样的,我这里主要是演示时区问题,数据操作细节问题就不再展示了。

首先我们来准备一个表,如下:

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `createTime` datetime DEFAULT NULL,
  `updateTime` timestamp NULL DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

很简单的几个字段,createTime 是 datetime 类型,updateTime 是 Timestamp 类型。

然后向表中添加一条记录:

MySQL时区造成时差问题

并且这个数据库的时区是 Asia/Shanghai

接下来我们创建一个 Spring Boot 项目,引入 Web、JDBC API 依赖和 MySQL 驱动,如下:

MySQL时区造成时差问题

然后我们来配置一下 MySQL 的连接信息,如下:

spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql:///test01?serverTimezone=UTC

小伙伴们看一下,在数据库连接地址中,我特意设置了时区为 UTC,这个时区比我们目前的时区慢了 8 小时,我们来看看用这样一个错误的时区,操作的结果是什么样子的。

@Autowired
JdbcTemplate jdbcTemplate;
@Test
void contextLoads() {
    List<User> list = jdbcTemplate.query("select * from user", new BeanPropertyRowMapper<>(User.class));
    System.out.println("list = " + list);
}

MySQL时区造成时差问题

大家看到,这个查询结果查到的时间是 21 点,跟 13 点相比快了 8 小时。

为啥呢?

因为我们连接地址中加了 serverTimezone=UTC 参数,这个时候,系统会把从数据库查询到的数据当成是 UTC 时区的,即把 13 点当成 UTC 时区的,但是我自己当前设备又是 Asia/Shanghai 时区,UTC 时区的 13 点转成 Asia/Shanghai 时区之后就是 21 点了。

相同道理,大家也可以自行尝试设置 serverTimezone=Asia/Tokyo,时区设置为东京,东京比我们早一个小时,东京的 13 点就是我们的 12 点,那么最终查询结果就是 12 点。

从这个案例中我们可以看到,jdbc 连接参数中的时区优先级高于 MySQL 服务器的时区参数,所以这个连接参数大家也要尤其注意。

3. 题外话

有的小伙伴遇到的时区问题则是另外一种,返回 JSON 的时候时间不对。

如果在项目中用了 jackson,并且使用 @JsonFormat 注解来格式化日期,就有可能出现时区问题,如下:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "Asia/Shanghai")

大家看到,这段代码如果没有设置 timezone 属性,那么默认的时区就是 UTC,也会导致最终的时间差了 8 小时。

4. 小结

到此这篇关于MySQL总是差八个小时该如何解决的文章就介绍到这了!

MySQL 相关文章推荐
MySQL Shell的介绍以及安装
Apr 24 MySQL
IDEA 链接Mysql数据库并执行查询操作的完整代码
May 20 MySQL
浅析MySQL如何实现事务隔离
Jun 26 MySQL
Mysql中where与on的区别及何时使用详析
Aug 04 MySQL
MySQL约束超详解
Sep 04 MySQL
MySQL悲观锁与乐观锁的实现方案
Nov 02 MySQL
详细聊一聊mysql的树形结构存储以及查询
Apr 05 MySQL
Mysql排查分析慢sql之explain实战案例
Apr 19 MySQL
MYSQL中文乱码问题的解决方案
Jun 14 MySQL
手把手带你彻底卸载MySQL数据库
Jun 14 MySQL
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
May 08 MySQL
Mysql调整优化之四种分区方式以及组合分区
Apr 13 #MySQL
聊聊mysql都有哪几种分区方式
Apr 13 #MySQL
MySQL分区以及建索引的方法总结
Apr 13 #MySQL
MySQL分区路径子分区再分区
Apr 13 #MySQL
MySQL创建管理子分区
Apr 13 #MySQL
MySQL创建管理KEY分区
Apr 13 #MySQL
MySQL创建管理HASH分区
Apr 13 #MySQL
You might like
PHP如何解决网站大流量与高并发的问题
2011/06/25 PHP
php为字符串前后添加指定数量字符的方法
2015/05/04 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
2017/10/13 PHP
Laravel框架实现定时Task Scheduling例子
2019/10/22 PHP
HTML颜色选择器实现代码
2010/11/23 Javascript
基于jQuery的图片左右无缝滚动插件
2012/05/23 Javascript
浏览器图片选择预览、旋转、批量上传的JS代码实现
2013/12/04 Javascript
JS对象转换为Jquery对象实现代码
2013/12/29 Javascript
JavaScript学习笔记之JS事件对象
2015/01/22 Javascript
JavaScript中的this关键字使用方法总结
2015/03/13 Javascript
HTML5之WebSocket入门3 -通信模型socket.io
2015/08/21 Javascript
jQuery实用技巧必备(上)
2015/11/02 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
2015/11/23 Javascript
JavaScript电子时钟倒计时
2016/01/09 Javascript
JavaScript基于replace+正则实现ES6的字符串模版功能
2017/04/25 Javascript
Webpack打包css后z-index被重新计算的解决方法
2017/06/18 Javascript
基于iScroll实现下拉刷新和上滑加载效果
2017/07/18 Javascript
Vue.js实现列表清单的操作方法
2017/11/15 Javascript
vue 监听某个div垂直滚动条下拉到底部的方法
2018/09/15 Javascript
vue实现的下拉框功能示例
2019/01/29 Javascript
Node如何后台数据库使用增删改查功能
2019/11/21 Javascript
ES5新增数组的实现方法
2020/05/12 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
[08:54]《一刀刀一天》之DOTA全时刻18:十九支奔赴西雅图队伍全部出炉
2014/06/04 DOTA
[02:05]2014DOTA2西雅图国际邀请赛 BBC第二天小组赛总结
2014/07/11 DOTA
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
python实现批量处理将图片粘贴到另一张图片上并保存
2019/12/12 Python
Django生成PDF文档显示网页上以及PDF中文显示乱码的解决方法
2019/12/17 Python
python中判断数字是否为质数的实例讲解
2020/12/06 Python
世界上最好的威士忌和烈性酒购买网站:The Whisky Exchange
2016/11/20 全球购物
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
学雷锋活动总结范文
2014/04/25 职场文书
拔河比赛口号
2014/06/10 职场文书
安全隐患整改报告
2014/11/06 职场文书
Python利用机器学习算法实现垃圾邮件的识别
2021/06/28 Python
Win10服务主机占用内存怎么办?Win10服务主机进程占用大量内存解决方法
2022/09/23 数码科技