文档章节

jdbc mysql connector 6 时区问题

purely
 purely
发布于 2017/07/21 17:20
字数 920
阅读 83
收藏 0
点赞 0
评论 0

起因

之前因为mysql connector 5的某个版本有OOM的风险: 传送门

所以调整了timeout时间和升级了connector到6.

一切以为都是正常的,不过却出现了一场惊天动地的抢险修复😂。

苦难

事情出在第二天,刚好周六。运营反馈说线上所有的贷款借据日期都不准了,差了14个小时。

于事在家里干紧vpn连上后,查看情况。

不看不知道,一看吓一跳,还真的TM都差了14个小时。这不是要人命吗,别说数据对不上,关这一天的利息就不知道多少钱了,想想就可怕啊。

分析

此时最需要的时冷静。待人静下心来,以及和同事沟通排查。这个程序上线半年多没出现这个问题,那么肯定是最近的更新导致的。最近的更新就是改了timeout和升级了 jdbc mysql connector的版本。timeout应该不会有问题,那问题很可能在connector上。

于是在本地新建一个工程用新版connector连上mysql试了一下,果然差了14个小时。

解决

问题找到了,那就要解决啊。一开始还真不知道怎么解决,问题找到了,然没有查到根本原因啊。后面查了查万能的google,发现在jdbc的url里指定timezone为东8区就可以了,如下

serverTimezone=GMT%2b8:00

这里的%2b是url encode后的+,decode后就是serverTimezone=GMT+8:00

原理

既然知道怎么解决了,在解决完问题,修复数据后,必须要查清楚具体原因。后来仔细排查下来,要jdk的文档中找到了答案。

先来看一下mysql的时区设置:

show variables like '%time_zone%';
system_time_zone	CST
time_zone	SYSTEM

可以看出system_time_zone是CST,也就是东8区,time_zone用的是SYSTEM,那也就是system_time_zone的CST。

然后再看一下connector里怎么处理时区的,在ConnectionImpl类中,有一个

 private void initializePropsFromServer() throws SQLException

在里面可以看到初时化时区的方法

this.session.configureTimezone();

点进去查看

   public void configureTimezone() {
        String configuredTimeZoneOnServer = getServerVariable("time_zone");

        if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
            configuredTimeZoneOnServer = getServerVariable("system_time_zone");
        }

        String canonicalTimezone = getPropertySet().getStringReadableProperty(PropertyDefinitions.PNAME_serverTimezone).getValue();

        if (configuredTimeZoneOnServer != null) {
            // user can override this with driver properties, so don't detect if that's the case
            if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {
                try {
                    canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());
                } catch (IllegalArgumentException iae) {
                    throw ExceptionFactory.createException(WrongArgumentException.class, iae.getMessage(), getExceptionInterceptor());
                }
            }
        }

        if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
            this.serverTimezoneTZ = TimeZone.getTimeZone(canonicalTimezone);

            //
            // The Calendar class has the behavior of mapping unknown timezones to 'GMT' instead of throwing an exception, so we must check for this...
            //
            if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverTimezoneTZ.getID().equals("GMT")) {
                throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[] { canonicalTimezone }),
                        getExceptionInterceptor());
            }
        }

        this.defaultTimeZone = this.serverTimezoneTZ;
    }

这里的PropertyDefinitions.PNAME_serverTimezone就是jdbc url上的serverTimezone变量,

可以很清楚地看出优先使用serverTimezon变量,如果没有,则用mysql的time_zone。

在没有serverTimezone变量时,读取mysql的time_zone为SYSTEM, 则进一步读取system_time_zone,也就是CST。

然后用CST做为时区,那问题来了,CST不就是东8区吗,怎么会有问题?

查看jdk的TimeZone类,看到注释中有这个一句:

* For compatibility with JDK 1.1.x, some other three-letter time zone IDs
* (such as "PST", "CTT", "AST") are also supported. However, <strong>their
* use is deprecated</strong> because the same abbreviation is often used
* for multiple time zones (for example, "CST" could be U.S. "Central Standard
* Time" and "China Standard Time"), and the Java platform can then only
* recognize one of them.

看到坑了没?CST可以是美国的中央时区,也可以是中国标准时区。所以现在问题已经找到了。

  1. 在mysql中CST代表的是中国标准时区,东8区。
  2. 在jdk中,CST代表的是美国中央时区

所以这里就出现在时区错乱的现象。

在jdk中,CTT表示东8区,所以也可以用serverTimezone=CTT,不过最好用GMT+8:00

ps:jdk版本1.8

------

© 著作权归作者所有

共有 人打赏支持
purely

purely

粉丝 18
博文 18
码字总数 8155
作品 0
杭州
高级程序员
Multi-Host Connections(三)

ReplicationDriver 针对Master/Slave,Mysql jdbc drivrer : ReplicationDriver https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-master-slave-replication-connection.html http......

墨子Zhai ⋅ 06/06 ⋅ 0

大型互联网架构必备技术——性能调优专题

性能调优 深入内核,直击故障 ,拒绝蒙圈 性能优化如何理解 1、性能基准 2、什么是性能优化 3、衡量标准 JVM调优 1、Jvm虚拟机内存剖析 2、垃圾收集器 3、实战调优案例与解决方案 4、Jvm运行...

Java高级架构 ⋅ 04/15 ⋅ 0

CDH安装系统环境准备——系统版本和安装包下载地址指南

由于Hadoop深受客户欢迎,许多公司都推出了各自版本的Hadoop,也有一些公司则围绕Hadoop开发产品。在Hadoop生态系统中,规模最大、知名度最高的公司则是Cloudera。接下来的日子里,小编将带大...

pengdongcheng ⋅ 04/23 ⋅ 0

CDH5.11.2安装启动hive 启动失败解决办法

1,通过Cloudera Manager添加Hive服务,在启动Hive的时候遇到错误: .org.apache.hadoop.hive.metastore.HiveMetaException: Failed to load driver 这种情况,猜测是缺少jdbc驱动,于是添加j...

小黑放大 ⋅ 05/25 ⋅ 0

MySQL Connector to J 8.0 Q&A

Connection Q:Driver/Datasource Class Name A:  低版本:com.mysql.jdbc.Driver  高版本(5.7+):com.mysql.cj.jdbc.Driver Q:Connection URL Syntax A: This is the generic format of th......

chaooWoo ⋅ 06/11 ⋅ 0

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prep

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(Abst......

黄柳淞 ⋅ 05/12 ⋅ 0

使用Hibernate+MySql+native SQL的BUG,以及解决办法

本来是mssql+hibernate+native SQL 应用的很和谐 但是到了把mssql换成mysql,就出了错(同样的数据结构和数据)。 查询方法是: 错误信息: 看到最后Caused by: java.sql.SQLException: 所以我...

thinkyoung ⋅ 2015/01/15 ⋅ 0

CentOS配置Gerrit Gitlab Jenkins--安装Gerrit(2)

1、下载Gerrit 可能需要翻墙,下载地址:https://www.gerritcodereview.com,我下载的版本是2.15.2 2、安装Gerrit 登录CentOS gerrit用户,执行java -jar gerrit-2.15.2.war inti -d /home/g...

Huangchp ⋅ 05/31 ⋅ 0

Jira7.4+Confluence集成环境的搭建5.10

一、环境准备 jira7.4的运行是依赖java环境的,也就是说需要安装jdk并且要是1.8以上版本,如下: wget http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aa...

秦时明月路 ⋅ 05/17 ⋅ 0

Confluence 平台部署记录

1.1 Confluence简介   Confluence是一个专业的企业知识管理与协同软件,也可以用于构建企业wiki。使用简单,但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息、文档协作、集体讨...

惨绿少年 ⋅ 2017/12/28 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Mahout推荐算法API详解

前言 用Mahout来构建推荐系统,是一件既简单又困难的事情。简单是因为Mahout完整地封装了“协同过滤”算法,并实现了并行化,提供非常简单的API接口;困难是因为我们不了解算法细节,很难去根...

xiaomin0322 ⋅ 21分钟前 ⋅ 0

WampServer默认web服务器根目录位置

安装WampServer之后的web服务器根目录默认位置在WampServer安装目录下的www:

临江仙卜算子 ⋅ 22分钟前 ⋅ 0

Redux的一些手法记录

Redux Redux的基本概念见另一篇文。 这里记录一下Redux在项目中的实际操作的手法。 actions 首先定义action.js,actions的type,可以另起一个action-type.js文件。 action-type.js用来存...

LinearLaw ⋅ 23分钟前 ⋅ 0

android 手势检测(左右滑动、上下滑动)

GestureDetector类可以让我们快速的处理手势事件,如点击,滑动等。 使用GestureDetector分三步: 1. 定义GestureDetector类 2. 初始化手势类,同时设置手势监听 3. 将touch事件交给gesture...

王先森oO ⋅ 37分钟前 ⋅ 0

java 方法的执行时间监控 设置超时(Future 接口)

java 方法的执行时间监控 设置超时(Future 接口) import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor......

青峰Jun19er ⋅ 42分钟前 ⋅ 0

一名开源小白的Apache成长自述

今天收到了来自Apache Vote我成为Serviceomb项目Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大...

微服务框架 ⋅ 44分钟前 ⋅ 0

vim介绍、颜色显示和移动光标、一般模式下复制、剪切和粘贴

1.vim 是 vi 的升级版 vim 是带有颜色显示的 mini安装的系统,一般都不带有vim [root@aminglinux-128 ~]# yum install -y vim-enhanced已加载插件:fastestmirror, langpacksLoading mir...

oschina130111 ⋅ 44分钟前 ⋅ 0

Deepin 操作系统四面楚歌

作为国内做的最好的 Linux 发行版,源自 Debian sid 的 Deepin 目前正面临重重困境,新版本不断延期,开发人员离职,bug 长期得不到修复,和 Debian/Ubuntu 的兼容性问题也面临越来越严重的挑...

六库科技 ⋅ 45分钟前 ⋅ 0

MyBatis之动态sql

我们需要知道的是,使用mybatis重点是对sql的灵活解析和处理。在原先的UserMappser.xml中,我们这样查询表中满足条件的记录 : 123 <select id="findUserList" parameterType="userQuery...

瑟青豆 ⋅ 45分钟前 ⋅ 0

这届俄罗斯世界杯的冷门那么多怎么办?

最纯粹的世界杯,最神奇的大冷门。 德国0比1被墨西哥摩擦了。 日本历史性的赢了哥伦比亚。 C罗也挑平了西班牙。 梅西被冰岛狮吼吼愣神了。 就连11次进世界杯4强的巴西也被瑞士逼平了。 天台已...

开源中国众包平台 ⋅ 46分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部