一次JDBC与MySQL因“CST”时区协商误解导致时间差了13或14个小时 推荐 原创 Mr大表哥 2019-01-09 22:22:37 博主文章分类:java日常问题汇总 ©著作权 文章标签 JDBC mysql CST 文章分类 运维 ©著作权归作者所有:来自51CTO博客作者Mr大表哥的原创作品,请联系作者获取转载授权,否则将追究法律责任 一、知识扫盲 JDBC:全称是java DataBase Connectivity 中文意思是java数据库连接 解释就是用于java编程语言和数据库之间的数据库无关的标准java API 二、错误展示 错误不好描述,直接看图: 三、分析原因 在服务器上执行“date”,看到时间,看到有CST字样 [root@dabiaoge ~]# date Wed Jan 9 21:54:23 CST 2019 继续知识点扫盲: CST时区 名为CST的时区是一个很混乱的时区,有四种含义: 美国中部时区Central Standard Time(USA)UTC-06:00 澳大利亚中部时区中央标准时间(澳大利亚)UTC + 09:30 中国标准时中国标准时区UTC + 08:00 古巴标准时古巴标准时区UTC-04:00 原因:CST的时区是一个很混乱的时区,在与MySQL协商会话时区时,Java会误以为是CST -0500或者CST -0600,而非CST +0800 解释原因是什么意思: 先来了解下美国的时区变化历史,美国规定每年从“3月11日”至“11月7日”实行夏令时,美国中部时区改为UTC-05:00;而“11月7日”至“3月11日”实行冬令时,美国中部时区改为UTC-06:00,博主的线上问题发现的时间是2019年1月9日,而此时美国中部的时区是UTC0600,而我们的时区是UTC0800,所以6+8=14个小时,因此线上的错误时间相隔14个小时。 四、排错过程 在项目中,偶然发现数据库中存储的 Timestamp 字段的 unix_timestamp() 值比真实值少了 14 个小时。通过调试追踪,发现了 com.mysql.cj.jdbc 里的时区协商有问题。 当 JDBC 与 MySQL 开始建立连接时,会调用 com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer() 获取服务器参数,其中我们看到调用 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 ... } } this.defaultTimeZOne= this.serverTimezoneTZ; } 追踪代码可知,当 MySQL 的 time_zone 值为 SYSTEM 时,会取 system_time_zone 值作为协调时区。 让我们登录到 MySQL 服务器验证这两个值: mysql> show variables like '%time_zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.00 sec) 重点在这里!若 String configuredTimeZoneOnServer 得到的是 CST 那么 Java 会误以为这是 CST -0600 ,因此 TimeZone.getTimeZone(canonicalTimezone) 会给出错误的时区信息。debug variables 本机默认时区是 Asia/Shanghai +0800 ,误认为服务器时区为 CST -0600 ,实际上服务器是 CST +0800 。 我们会想到,即便时区有误解,如果 Timestamp 是以 long 表示的时间戳传输,也不会出现问题,下面让我们追踪到 com.mysql.cj.jdbc.PreparedStatement.setTimestamp() public void setTimestamp(int parameterIndex, Timestamp x) throws java.sql.SQLException { synchronized (checkClosed().getConnectionMutex()) { setTimestampInternal(parameterIndex, x, this.session.getDefaultTimeZone()); } } 注意到这里 this.session.getDefaultTimeZone() 得到的是刚才那个 CST -0600 private void setTimestampInternal(int parameterIndex, Timestamp x, TimeZone tz) throws SQLException { if (x == null) { setNull(parameterIndex, MysqlType.TIMESTAMP); } else { if (!this.sendFractionalSeconds.getValue()) { x = TimeUtil.truncateFractionalSeconds(x); } this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = MysqlType.TIMESTAMP; if (this.tsdf == null) { this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); } this.tsdf.setTimeZone(tz); StringBuffer buf = new StringBuffer(); buf.append(this.tsdf.format(x)); if (this.session.serverSupportsFracSecs()) { buf.append('.'); buf.append(TimeUtil.formatNanos(x.getNanos(), true)); } buf.append('\''); setInternal(parameterIndex, buf.toString()); } } 原来 Timestamp 被转换为会话时区的时间字符串了。问题到此已然明晰: JDBC 误认为会话时区在 CST-6 JBDC 把 Timestamp+0 转为 CST-6 的 String-6 MySQL 认为会话时区在 CST+8,将 String-6 转为 Timestamp-14 最终结果相差 14个小时!如果处在夏令时还会相差 13个小时 五、解决方法 解决办法非常的简单,手动明确指定 MySQL 数据库的时区,不使用引发误解的 CST: 临时生效: mysql> set global time_zOne= '+08:00'; Query OK, 0 rows affected (0.00 sec) mysql> set time_zOne= '+08:00'; Query OK, 0 rows affected (0.00 sec) 永久生效(修改后需要重启mysql): 修改 my.cnf 文件,在 **[mysqld] 节下增加 default-time-zOne= '+08:00' ** 赞 收藏 评论 分享 举报 上一篇:言简意赅解释Linux中的标准输入输出 下一篇:java密钥长度受限制问题解决 提问和评论都可以,用心的回复会被更多人看到 评论 发布评论 全部评论 () 最热 最新 相关文章 一小时解决听上去很严重的网络故障 一年前被邀请去解决复杂问题的客户,昨天上午网络又出故障,客户描述:有线网线有部分楼层无法上网,无线网络大面积无法获取到IP地址,10个AP有7个掉线。关键是,出故障的前一天,客户还在问我要核心交换机的密码,我能给出的密码,显然早就不对了,IT离职数月,中间真空了几个月,现在的IT刚入职没几天,听听就头大。客户的需求就是命令,毕竟产线停产的损失一时难以计算,恐怕也没心情计算吧,于是立刻驱车前往。一路 配置文件 IT 重置 交换机 华为 【MySQL】-多表设计(一对多、一对一、多对多) 概述项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:1.一对多(多对一)2.多对多3.一对一一、一对多需求:根据页面原型及需求文档,完成部门(一)及员工(多)模块的表结构设计一对多关系的实现:在数据库表中多的一方,添加字段,来关联一的一方的主键。现在我们插入数据分析insert i 外键 主键 一对一 一对多 多对多 Ubuntu之修改时区/时间 查看当前时间及时区状态sudo timedatectl status# 显示当前时区为Asia/Shanghai查看当前系统时间sudo date查看当前系统时间及时区sudo date -R# 显示当前时间及对应时区,时区为“+0800”北京时区修改硬件时间修改日期格式:MM月/DD日/YYYY年sudo date -s MM/DD/YYYY修改时间:hh时:mm分:ss秒 sudo date ubuntu修改时区 ubuntu修改时间 ubuntu修改时间及时区 ubuntu修改时区和时间 ubuntu修改系统时间 mysql cst 8小时 # MySQL CST 8小时MySQL 是一个流行的开源关系型数据库管理系统,广泛应用于各种 Web 应用程序中。在这篇文章中,我们将介绍如何使用 MySQL 进行存储和检索数据,并且讲解如何在 CST 8 小时内学会基本的 MySQL 操作。## MySQL 简介MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前由 Oracle 公司维护。MySQL MySQL sql 数据 mysql 设置CST时区 # MySQL设置CST时区## 介绍在使用MySQL数据库时,经常需要设置合适的时区来保证数据的一致性和准确性。本文将介绍如何在MySQL中设置CST(中国标准时间)时区。## 流程图```mermaidflowchart TD subgraph 准备工作 A(连接MySQL数据库) --> B(查看当前时区设置) end subgraph MySQL 数据库 sql mysql时区 cst ## MySQL时区介绍及应用MySQL是一种常用的关系型数据库管理系统,它能够高效地处理大规模数据存储和管理。在MySQL中,时区是一个重要的概念,它可以用来确定日期和时间的显示和存储方式。本文将为您介绍MySQL时区的相关知识,并提供代码示例来帮助您更好地理解和应用时区概念。### 什么是时区?时区是指地球上不同地区根据其经度的不同,把时间按照一定规则调整的过程。在全球范围内,共有 MySQL sql 自定义 docker 时区相差8小时 # Docker时区相差8小时的实现方法## 介绍在Docker容器中,时区默认是UTC时间,与我们常用的时区相差8个小时。为了解决这个问题,我们可以通过设置容器的时区来使其与宿主机的时区保持一致。本文将介绍如何在Docker中实现时区相差8小时的方法。## 步骤概览下面是实现Docker时区相差8小时的步骤概览:| 步骤 | 操作 || --- | --- || 1 | 创建 Dockerfile 环境变量 Docker Dockerfile中设置cst时区 ## Dockerfile中设置CST时区在使用Docker容器化应用程序时,我们可能需要设置容器的时区以保证时间的正确显示。本文将介绍如何在Dockerfile中设置CST(China Standard Time)时区,并提供相关的代码示例。### 什么是Dockerfile?Dockerfile是用于构建Docker镜像的文本文件,其中包含一系列的指令和配置。通过Dockerfil Dockerfile Docker 应用程序 docker镜像时区差8小时 # Docker镜像时区差8小时在使用Docker容器时,经常会遇到时区不匹配的问题。特别是当容器运行在不同的时区时,容器内部的时间会与宿主机的时间存在差异。本文将介绍如何解决Docker镜像时区差8小时的问题,并提供相应的代码示例。## 问题描述当我们在Docker容器中运行一个应用程序时,容器内部的时区通常会与宿主机的时区不一致。这会导致容器内部的时间和日期与我们期望的时间不符。特 Docker 环境变量设置 类图 Mysql入门到精通-相差8小时mysql时区配置 这篇文章主要介绍了MySQL修改时区的方法,总结分析了三种常见的MySQL时区修改技巧,包括命 mysql 重启 初始化 Mysql修改时区(时间差8小时) 1、首先查看MySQL当前的时间SELECT now();show variables like "%time_zone%";time_zone 用来 mysql 重启 MySQL flink mysql cdc 时间多8小时 # Flink MySQL CDC 时间多8小时## 引言在使用 Apache Flink 进行实时数据处理时,我们有时需要从 MySQL 数据库中抓取变更数据。为了实现这一功能,我们可以使用 Flink 的 MySQL CDC(Change Data Capture)插件。然而,有时候我们在使用 CDC 过程中会发现抓取到的时间与实际时间相差8小时,这是因为 CDC 默认使用的是 UTC MySQL flink apache mysql timestamp 比datetime多8小时 # 如何实现mysql timestamp比datetime多8小时## 简介在mysql中,timestamp类型和datetime类型都用来存储日期和时间信息,但是它们有一些不同之处。其中一个最明显的区别就是timestamp类型会自动将存储的时间转换为UTC时间,而datetime类型则不会。如果需要让timestamp类型比datetime类型多8小时,可以通过调整时区来实现。下面将 mysql mysql数据库 代码示例 mantis时区差8小时的修改 mantis时区差8小时的修改 在config_ini.php中加一句putenv("TZ=Asia/Shanghai");php.ini中的改为date.timezOne= PRC 最后修改一下个人帐户的时区个人资料→更改个人设置→时区 ... mantis mantisBT php docker compose jar 时区相差8小时 # Docker Compose JAR 时区相差8小时在使用Docker Compose构建Java应用程序时,我们有时会遇到时区差异的问题。特别是在处理日期和时间时,时区的不匹配可能导致错误的计算和显示。本文将介绍如何解决使用Docker Compose构建的JAR包中的时区差异问题,并提供相关的代码示例。## 问题描述当我们在Docker容器中运行Java应用程序时,默认情况下容 应用程序 Docker Java CentOS 7 时区设置 EST和CST设置 edatectl status Local time: Sat 2019-11-09 22:23:58 EST Universal time: S Universal Time CentOS linux设置时间为24小时制,设置时区 1. 查看系统时间[root@localhost.localdomain ~]#dateThu Feb 4 14:24:18 CST 2010时区是CST,为了彻底弄明白GMT,UTC,CST,我查阅了下网上的相关教程,进行整理:一般来说,UTC(Coordinated Universal Time世界协调时间)与GMT(格林威治时间 Greenwich Mean Time) 是等 linux设定时区 coms时间同步 设定时间为24小时制 mysql 时区少了8小时 mysql 时区和时间的问题 问题:查询不同数据库上表中记录时间差距8小时。昨天协助其他地区同事解决客户查询到不同数据中心时间差距8小时的问题。原因就是时区不同。解决方案:设置服务器的时区都为北京时间,即修改数据库服务器的time_zone值为“+8:00”解决。这个参数,可以在通过mysqld命令启动数据库的时候加上参数 --default-time-zOne=timezone来设置时区,也可以通过my.cnf配置 mysql 时区少了8小时 字段 数据库 表数据 docker 时区相差8小时 docker容器时区 前言全球不同的地方有不同的时区划分,所有了以全球标准时间(UTC)和本地时间(localtime)区别。一般我们都设置成本地时间,方便操作与统计。机器里有两个时钟,硬件时钟从根本上讲是CMOS时钟,而系统时钟是由内核维护的。查看docker容器时间及时区date 或者data -R 时间时区修改第一种修改方法:使用命令修改(使用root确保有权限),根据提示一步步修改就可以了 系统时间 修改时间 时间同步 mysql 时区相差1小时 mysql时区报错原因 前言:在使用 MySQL 的过程中,你可能会遇到时区相关问题,比如说时间显示错误、时区不是东八区、程序取得的时间和数据库存储的时间不一致等等问题。其实,这些问题都与数据库时区设置有关,本篇文章将从数据库参数入手,逐步介绍时区相关内容。1.log_timestamps 参数介绍首先说明下log_timestamps参数并不影响时区,只是设置不同会影响某些日志记录的时间。该参数主要是控制 error mysql 时区相差1小时 mysql spring 数据库 MySQL