00. 基本问题

0.0 版本: 驱动5.1.47和8.0.17
0.1 MySQL驱动5.1有userLegacyDatetimeCode和userTimezone两个参数, 8.0没有
0.2 Java与MySQL间传递时间戳的时候, 传递的是年月日时分秒, 没有时区
0.3 MySQL传递回来的是: MySQL读取到底层存储的时间戳, 按照当前连接(MySQL侧)的时区转为年月日时分秒
0.4 但是, 两个系统时区可能会不同, userLegacyDatetimeCode和userTimezone就是用来协调时区的

01. MySQL驱动5.1

1.1 数据库连接在建立时, 会创建一个Calendar对象保存在连接中, 其中保存了连接创建时的时区, 即下文的"连接时区". 见ConnectionImpl#705
1.2 如果配置了serverTimezone,则会将其保存到连接中, 即下文的"配置时区". 见ConnectionImpl#1978
1.3 userLegacyDatetimeCod=true&userTimezone=false, 这是默认情况
1.3.1 此时对应Java和MySQL时区相同
1.3.2 Java接收到MySQL传递来的年月日时分秒, 加上"连接时区"创建时间戳java.sql.Timestamp, 见ResultSetImpl#5877和TimeUtil#369
1.4 userLegacyDatetimeCod=true&userTimezone=true&serverTimezone=GMT%2B6
1.4.0 userTimezone=true, 必须在userLegacyDatetimeCod=true时才有效
1.4.1 此时对应二者时区不同
1.4.2 与3.2相同, 先将年月日时分秒+"连接时区", 创建时间戳
1.4.3 再进行时区调整, 调整为"配置时区". 见ResultSetImpl#5877和TimeUtil#160
1.5 userLegacyDatetimeCod=false&serverTimezone=GMT%2B6
1.5.1 此时对应二者时区不同
1.5.2 将年月日时分秒+"配置时区"创建时间戳. 见ResultSetImpl#5874
1.5.3 这也是8.0的处理方式

02. MySQL驱动8.0

2.1 8.0没有userLegacyDatetimeCode和userTimezone两个参数
2.2 一定要配置serverTimezone为MySQL运行的时区. 连接建立时会将这个时区存储到连接中. 见NativeProtocol#2147#2158
2.3 将年月日时分秒+"配置时区"构造时间戳. 见SqlTimestampValueFactory#100. 这里的cal就是在#68根据"配置时区"创建的

03. 代码跟踪中的一些关键点

版本5.1

连接初始化的过程

  1. ConnectionImpl#1978 "配置时区"
  2. ConnectionImpl#705 将当前时区保存到了数据库连接中

读取的过程

  1. MyBatis的各个TypeHandler
  2. ByteArrayRow#63 拿到字节数组
  3. ResultSetRow#705 将字节数组转为字符串
  4. ResultSetImpl#5729 将字符串分离为年月日时分秒
  5. ResultSetImpl#5873 对应上文01.5.2
  6. ResultSetImpl#5877 对应上文01.4.2和01.4.3
  7. ResultSetImpl#5317 如果Java要返回的是String, 则会在这里将时间戳转为jvm当前时区下的年月日时分秒

版本8.0

  1. NativeProtocol#2147#2158 保存"配置时区"
  2. ByteArrayRow#89 拿到数据库返回的字节, 大致相当于 01.5.1的ByteArrayRow#63
  3. MysqlTextValueDecoder#338 解析字节数组, 拿到年月日时分秒并封装为InternalTimestamp
  4. SqlTimestampValueFactory#100 也就是上文02.3
  5. StringValueFactory#94 如果Java要返回的是String, 就直接将InternalTimestamp转为字符串, 不考虑当前系统时区了, 与5.1的第7条有区别
  6. AbstractResultSetRow#78
  7. PropertyKey jdbc url的property的key枚举类, https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html

04. The server time zone value '???DZ?׼ʱ?' is unrecognized or represents more than one time zone 异常是怎么回事?

在三种情况下会抛出
上文01.4/01.5/02.2情况下未配置serverTimezone是都会抛出
因为, NativeProtocol#2130或者ConnectionImpl#1960拿到数据库的system_time_zone是乱码, 也就是select @@system_time_zone 的值
所以要配置serverTimezone为数据库运行的时区

05. 问题

时间戳传递为什么不是一个数字形式的秒/毫秒呢, 而是一个没有时区的年月日时分秒呢? 还得协调时区, 多复杂呢?

0078 Java与MySQL时间戳传递/存储/协调问题--userLegacyDatetimeCode--userTimezone--serverTimezone的更多相关文章

  1. Mysql时间戳转Java时间戳

    MySQL 时间戳和Java返回的时间戳是不一样的 例如: 当前时间是 2014-08-04 10:42:55.204000 使用mysql时间戳函数UNIX_TIMESTAMP 返回的结果为: 14 ...

  2. java和mysql之间的时间日期类型传递

    摘自:http://blog.csdn.net/weinianjie1/article/details/6310770 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8byt ...

  3. 理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  4. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)

    最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  5. FROM_UNIXTIME 格式化MYSQL时间戳函数

    FROM_UNIXTIME 格式化MYSQL时间戳函数 对MYSQL没有进行过深入的研究,基础知识匮乏,一遇到问题只能手册,看来要把MYSQL的学习安排进时间表了. 函数:FROM_UNIXTIME作 ...

  6. Java连接MySQL数据库及简单操作代码

    1.Java连接MySQL数据库 Java连接MySql需要下载JDBC驱动MySQL-connector-java-5.0.5.zip(举例,现有新版本).然后将其解压缩到任一目录.我是解压到D盘, ...

  7. Java网页数据采集器[中篇-数据存储]【转载】

    本期概述 上期我们学习了html页面的数据采集,为了方便我们今后来调用收集到的数据,首先我们需要学习下如何将这些采集到的数据存储起来(MySql数据库). 数据采集页面 2011-2012赛季英超球队 ...

  8. 转载:Java连接MySQL 数据库的正确操作流程

    转载网址:http://www.bitscn.com/pdb/mysql/201005/186551.html       以下的文章主要介绍的是Java连接MySQL 数据库(以MySQL数据库为例 ...

  9. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包括增删改查、JavaBean反射原理,附源代码)

    近期看老罗的视频,跟着完毕了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完毕对数据库的增删改查.当中查询这块,包含普通的查询和利用反射完毕的查询,主要包含以下几个函数接口 ...

随机推荐

  1. Python 数字(函数)

    Python支持4种不同数值类型: 整型(Int) - 通常被称为是整型或整数,是正或负整数,不带小数点. 长整型(long integers) - 无限大小的整数,整数最后是一个大写或小写的L. 浮 ...

  2. 微信小程序异步回调

    场景如下:现有一个方法需要等待其他N个异步函数执行完毕后执行,callback麻烦的头大,翻了一波API原来小程序已经支持 async函数,那一切就好办了. 废话不多说,直接开始撸... 第一步:打开 ...

  3. JS-实现横向手风琴

    横向手风琴-- 鼠标悬浮某一张图片,图片显示,其他图片影藏. <div class="content"> <ul> <li class="c ...

  4. 微信小程序编译提示tabar.iconPath 文件不存在

    tabBar.list[0].iconPath 文件不存在 明明是按路径放了本地图片的,却依然显示路径不存在 需要把路径的图片转移到编译后的weapp文件中相同路径下的img文件中 本地正常路径 粘贴 ...

  5. mock.js学习之路一(Vue中使用)

    1.安装mockjs 2.配置mockjs在开发环境中启用,生产环境中禁用 3.创建mock文件夹,以及mock数据文件 4.在main.js中引入与否 5.页面获取数据 testMock(){ th ...

  6. C# PDF 填值 填充数据

    看效果图   /// <summary> /// 赛事结果PDF /// </summary> /// <param name="model"> ...

  7. mysql主备搭建

    mysql主备搭建参考文档https://www.cnblogs.com/clsn/p/8150036.html前提条件:系统:Ubuntu 16.04.6 LTSMySQL版本:5.7.24主库IP ...

  8. 使用Fiddler工具在夜神模拟器或手机上抓包

    下载安装Fiddler 地址:https://www.telerik.com/download/fiddler-everywhere Fiddler端设置 Tools>Options>Co ...

  9. Django_03_后台管理

    后台管理 站点分为内容发布和公共访问两部分 内容发布的部分由网站的管理员负责查看.添加.修改.删除数据,开发这些重复的功能是一件单调乏味.缺乏创造力的工作,为此,Django能够根据定义的模型类自动地 ...

  10. javascript代码模块化解决方案

    我们用模块化的思想进行网页的编写是为了更好的管理我们的项目,模块与模块之间是独立存在的,每个模块可以独立的完成一个子功能. 一.服务器和桌面环境中的Javascript代码模块化:CommonJS M ...