Java 中的 Mysql 时区问题
(Photo by Andrea Piacquadio from Pexels)
话说工作十多年,mysql 还真没用几年。起初是外企银行,无法直接接触到 DB;后来一直从事架构方面,也多是解决问题为主。
这次搭建海外机房,围绕时区大家做了一番讨论。不说最终的结果是什么,期间有同事认为 DB 返回的是 UTC 时间。
这里简单做个验证,顺便看下时区的问题到底是如何处理。
环境
openjdk version “1.8.0_242” mysql-connector-java “8.0.20” mysql “5.7” 时区 TZ=Europe/London 本地时区 GMT+8
创建个简单的库test
及表user
, 表结构如下:
插入一条测试数据:
测试代码:
执行结果:
分析
程序的执行过程同时用 wireshark 抓了包。可以看到一次查询,做了这么多次的交互(包含了会话初始化)。这里可以看到 #177 的交互返回查询的结果:Tom 2020-05-14 08:00:00
,与 DB 中的数据相符。可见,返回的并不是 UTC 时间。
在 TCP 抓包结果中 #155 的查询语句:
服务端返回的 time_zone
为 BST
。与本地时区的转换,由 mysql 的 connector 自动完成。
进阶
时区自动转换
实现源码:
ResultSetImpl
源码
如何确认服务端时区?
使用会话中的服务端时区进行服务端时区。会话初始化时会进行时区的确认,比如前面获取的到BST
。确认时区的逻辑在NativeProtocol#configureTimezone()
中:
关于 serverTimezone 的官方说明
Override detection/mapping of time zone. Used when time zone from server doesn’t map to Java time zone
修改一下 jdbc url,通过serverTimezone
指定时区为 GMT+8
:jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false
再次执行代码:
评论