The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone-程序员宅基地

技术标签: �й���׼ʱ��  time zone  时区  mysql  

前言:最近,因为复习JDBC知识,使用了最新版本的mysql驱动程序(mysql-connector-java.jar),结果出现了之前从未遇到过的问题:The server time zone value ‘�й���׼ʱ��’ is unrecognized or represents more than one time zone。出于对未知的好奇,于是在网上查找出现该问题的具体原因,找了很久,浏览了许多文章,最常见的解答是:serverTimezone=UTC、serverTimezone=Asia/Shanghai或者降低mysql驱动程序的版本。但是,几乎没有看到有人解释问题发生的原因,也没有介绍time zone的概念,就只是给出来解决方法。在某篇博文中的评论中,我发现也有人问”为什么要这样设置(serverTimezone)“,有人回答mysql高版本驱动程序需要设置时区,这个答案让我感觉”听君一席话,如听一席话“,属于”废话文学“。最后,只能求助mysql官方文档,发现涉及到内容太多了,但是念念不忘,必有回响。坚持不懈了三天,总算对问题有了全面的认知。

一 、问题发生

系统环境:JDK 1.8、mysql-connector-java 8.0.23(mysql驱动程序)、mysql数据库 8.0.28

代码如下:

String url = "jdbc:mysql://localhost:3306/crashcourse?useUnicode=true&characterEncoding=utf8";

Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, "root", "admin");

// 其他与数据库交互的代码省略

在IDEA运行后,出现错误,如下图所示:

在这里插入图片描述

二、 问题解决

报错信息中,包含了对解决问题方法的描述。

You must configure either the server or JDBC driver (via the ‘serverTimezone’ configuration property) to use a more specifc time zone value if you want to utilize time zone support.

翻译:如果你想运用时区支持,必须配置服务器JDBC驱动程序(通过’ serverTimezone '配置属性)来使用更具体的时区值。

解决方案一:配置服务器

1. 临时配置

重启服务器会失效。使用具有权限的(配置全局变量,可以是root用户)用户,登陆到mysql服务器,运行以下命令:

mysql> set global time_zone='+8:00';
Query OK, 0 rows affected (0.00 sec)

2. 永久配置

在my.ini中添加配置项(Windwos系统中,my.ini文件位置:C:\ProgramData\MySQL\MySQL Server 8.0),重启服务器生效。

[mysqld]
default-time-zone = '+8:00'

解决方案二:配置JDBC驱动程序

通过serverTimezone配置连接的属性,即在url中添加serverTimezone=UTC参数。

另外,serverTimezone的值除了UTC外,还可以设置Asia/ShanghaiGMT%2b8(URL编码),把会话(也就是客户端与服务器的链接)的时区设置为东八区。

String url = "jdbc:mysql://localhost:3306/crashcourse?serverTimezone=Asia/Shanghai
JDBC的会话时区如果不配置,默认使用服务器的全局时区配置。 上述配置虽然不会报错,但是不会发挥作用。如果想要时区发挥作用还需要配置useTimezone参数。正确做法是 String url = "jdbc:mysql://localhost:3306/crashcourse?serverTimezone=Asia/Shanghai&useTimezone=true

关于serverTimezone取值的格式:https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-datetime-types-processing.html

serverTimezone 只在客户端发挥作用,并不实际修改会话time_zone的值
例如,

JVM Connecter serverTimezone utc+9 server utc+8 底层
UTC+8 8 -9 utc+1

解决方案三:使用低版本驱动程序

我觉得,严格来说,这不算是问题的解决方法,而是逃避问题的手段。如果你不想了解时区是什么及如何设置,像快点学习JDBC开发技术,这也是一种选择。但是,可能会存在软件版本之间的兼容问题。

由于mysql的java驱动程序,在版本6.0.0及以上,才要求必须配置时区,因此,可以使用6.0.0以下版本的mysql-connector-java.jar,例如、比较稳定的版本5.1.49


至此问题已经解决。网上大部分的解答也差不多就是上面总结的情况。

但是,当我查看一些高赞博文的评论时,发现有人和我存在一样的困惑:”时区是什么,为什么会有时区问题?“
在这里插入图片描述

如果你也有这样的疑惑,请继续阅读下面的讲解。说实话,解决这个问题,两分钟都不需要,但是真正弄清楚问题的原因,需要花费很大努力。难能可贵嘛,加油,奥利给!


三、问题分析

”The server time zone value ‘�й���׼ʱ��’ is unrecognized“,服务器时区值’�й���׼ʱ��’是无法识别的,那么,这个乱码的值是什么?如果解决了乱码问题,是否就不会出现这个问题了呢?这是我遇到这个问题时,脑海里最初的想法。

介绍上述内容需要了解一些基础知识。

1. 时区系统变量

服务器系统变量(system variables),表示服务器运行中使用到配置选项。例如,配置服务器的端口号、字符集等等。可以在my.ini文件中配置,有些系统变量是动态的(dynamic),也可以在运行时使用SET 语句更改,这使你能够修改服务器的配置项而无需重启,即可生效。另外,全局系统变量(global system variables)对与所以会话(指的是一个mysql客户端到服务器的连接)都生效,会话系统变量(session system variables)只对当前会话有效,不影响其他会话。

和时区相关的系统变量:

  • 服务器系统时区。当服务器启动时,它会尝试确定主机的时区并使用它来设置 system_time_zone系统变量。
  • 服务器当前时区。全局 time_zone系统变量表示服务器当前运行的时区。初始time_zone 值为’SYSTEM’,表示服务器时区与系统时区相同。

如果设置为SYSTEM,(每个需要时区计算的 MySQL 函数调用)都会调用系统库来确定当前系统时区。

注意,两者的区别,服务器系统时区和我们的客户端程序(例如,JDBC程序)没有直接关系,而服务器当前时区是与我们的客户端程序有密切关系,我们使用的时区就是服务器当前时区。就好像character_set_server和character_set_system一样,system的编码用于服务器系统内部的编码,而server才和数据库的编码有联系。因此,会着重介绍服务器当前时区time_zone

设置全局系统变量语法:

全局系统变量,对所有会话有效,如果会话不覆盖系统变量,默认使用它

SET GLOBAL time_zone = timezone;

设置会话系统变量语法:

SET [SESSION | LOCAL | 省略] time_zone = timezone;

timezone值可以以多种格式给出,但都不区分大小写:

  • ‘SYSTEM’,表示服务器时区与系统时区相同。

  • 作为表示与 UTC 格式的偏移量的字符串 ,以or 为前缀,例如, 或。对于小于 10 的小时值,可以选择使用前导零;MySQL 在这种情况下存储和检索值时会添加前导零。MySQL 将 或转换为 . [H]H:MM±’+10:00’‘-6:00’‘+05:30’‘-00:00’‘-0:00’‘+00:00’在 MySQL 8.0.19 之前,这个值必须在 到 的范围内 ‘-12:59’,’+13:00’包括在内;从 MySQL 8.0.19 开始,允许的范围是’-13:59’to ‘+14:00’,包括在内。

  • 作为命名时区,例如 ‘Europe/Helsinki’、 ‘US/Eastern’、‘MET’或’UTC’。

查看系统变量语法:

SELECT @@GLOBAL.variableName;
SELECT @@SESSION.variableName;

variableName表示变量的名字,如果像查询时区系统变量,可以SELECT @@SESSION.time_zone;

另外,如果不知道变量的具体名字,也可以模糊查询

show variables like ‘匹配的条件字符串’;

2. 乱码的内容是什么

首先,使用root用户登录到服务器,执行代码:show variables like '%time_zone';

在这里插入图片描述
根据已有的知识,system_time_zone的时区值应该与我主机(windows10系统, 时区东八区,China Standard Time 中国标准时间。每个时区为了方便自己国际使用,都有一个名字。)的时区一致才对,然而这里显示的是空值。其实是有值的,mysql客户端对于乱码字符的处理方式有时候是选择不显示它。

执行代码: select @@global.system_time_zone;
发现果然是有值的,只是乱码而已
在这里插入图片描述
执行代码:set character_set_results = ‘utf8mb3’; 设置结果集编码后,在查看系统变量,发现值为"中国标准时间",这就与上文的介绍一致了。
至于,为什么设置编码为utf8mb3,这部分内容比较复杂,我会单独写一篇文章介绍。

在这里插入图片描述
前文介绍了,system_time_zone是和我们的客户端(JDBC程序)是无关的,如果JDBC没有设置会话的时区,默认使用全局的时区配置,也就是time_zone,上文也提到了,如果设置为’SYSTEM’,那么time_zone的时区是需要调用msyql的库函数获取的。我们的JDBC程序就是调用了msyql的库函数,返回值为“中国标准时间”。

至此,我们清楚了乱码的内容是“中国标准时间”。

对此,你也许会产生怀疑,我说JDBC程序就是调用了msyql的库函数,返回值为“中国标准时间”,实际底层是这样做的吗?如何能直接说明乱码就是“中国标准时间”呢。我来证明一下。

执行代码:select hex(@@global.system_time_zone);

hex()获取表中字符数据项目的在数据库表中的底层编码,可以看到返回值为:
(其实这是GBK编码的字符)。

(关于字符编码及乱码问题,可以参考这篇文章:《字符编码及乱码》,可以解决你日常遇到的所有乱码问题)

在这里插入图片描述
然后,我们使用解码工具,解码该字符编码

请添加图片描述
底层编码是GBK,但是mysql服务器却认为他是utf8mb3的,因此,必须声明解码类型为utf8mb3,而实际使用GBK解码。mysql提供的客户端程序可以做到这一点,上文中我们也看到了。但是我们的JDBC程序客户端,不可能做到这一点。因此,无法通过指定正确的编码来解决乱码问题。

3. 为什么要使用时区

先简单了解一下时区,全球被划分为24个时区,每差一个时区,区时相差一个小时。时区转换规则,“东加西减”。

例如、中国在东八区,日本在东九区,我现在的时间是22:30,那么日本现在是23:30。

在这里插入图片描述

时区表示方式:

  • UTC偏移量±[hh]:[mm]

  • 命名表示方式,例如东八区,可以使用名字China Standard Time (或者缩写CST,中国标准时间)

当然,从上图我们也可以知道,不同的国家或者地区可以处于相同的时区,为了方便使用,不同国家或地区可以根据自己的需要对相同时区定义不同的名字。例如、我们中国定义东八区为China Standard Time,中国台湾定义东八区为Taipei Standard Time。

(Windows10系统,通过在命令行窗口运行命令:tzutil /l 可以查看系统支持的时区)
在这里插入图片描述
我们对什么是时区有了初步的认识,下面说明使用时区的好处。

假设,我们建立了一个发布国际新闻的网站,首先建立一张表保存新闻信息,content字段存储新闻的内容,instant字段存储发布新闻的时间。

CREATE TABLE news(
	id INT UNSIGNED PRIMARY KEY,
	content VARCHAR(255) NOT NULL,
	instant TIMESTAMP NOT NULL
)

为了避免混乱,可以打开两个命令行窗口。

一位中国记者上传了一条新闻,设置了会话时区为东八区,然后上传了一条新闻

在这里插入图片描述
一位日本记者上传了一条新闻,设置会话时区为东九区,然后上传了一条新闻。

在这里插入图片描述

中国新闻媒体会这样报道新闻:
(注意,time_zone在会话期间,只需设置一次,我这里是为了体现命令所在的时区,因此每次执行命令,先设置时区)
在这里插入图片描述

  1. 4月4日,23点4分,震惊!某程序员晚上不睡觉,竟然为了这件事!
  2. 北京时间(中国标准时间),4月4日,23点5分,日本发生7.5级地震(原日文:日本でマグニチュード7.5の地震が発生)

在这里插入图片描述
设置时区后,当存储或者检索时间类型数据的时候会进行转换,依据时区设置。如果没有时区设置,那么,中国新闻媒体看到的日本记者发布的新闻时间是4月5日,0点5分。

4. 如何在mysql驱动程序中设置时区

请参考文章【mysql中的时区问题】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gao_zhennan/article/details/123953198

智能推荐

艾美捷Epigentek DNA样品的超声能量处理方案-程序员宅基地

文章浏览阅读15次。空化气泡的大小和相应的空化能量可以通过调整完全标度的振幅水平来操纵和数字控制。通过强调超声技术中的更高通量处理和防止样品污染,Epigentek EpiSonic超声仪可以轻松集成到现有的实验室工作流程中,并且特别适合与表观遗传学和下一代应用的兼容性。Epigentek的EpiSonic已成为一种有效的剪切设备,用于在染色质免疫沉淀技术中制备染色质样品,以及用于下一代测序平台的DNA文库制备。该装置的经济性及其多重样品的能力使其成为每个实验室拥有的经济高效的工具,而不仅仅是核心设施。

11、合宙Air模块Luat开发:通过http协议获取天气信息_合宙获取天气-程序员宅基地

文章浏览阅读4.2k次,点赞3次,收藏14次。目录点击这里查看所有博文  本系列博客,理论上适用于合宙的Air202、Air268、Air720x、Air720S以及最近发布的Air720U(我还没拿到样机,应该也能支持)。  先不管支不支持,如果你用的是合宙的模块,那都不妨一试,也许会有意外收获。  我使用的是Air720SL模块,如果在其他模块上不能用,那就是底层core固件暂时还没有支持,这里的代码是没有问题的。例程仅供参考!..._合宙获取天气

EasyMesh和802.11s对比-程序员宅基地

文章浏览阅读7.7k次,点赞2次,收藏41次。1 关于meshMesh的意思是网状物,以前读书的时候,在自动化领域有传感器自组网,zigbee、蓝牙等无线方式实现各个网络节点消息通信,通过各种算法,保证整个网络中所有节点信息能经过多跳最终传递到目的地,用于数据采集。十多年过去了,在无线路由器领域又把这个mesh概念翻炒了一下,各大品牌都推出了mesh路由器,大多数是3个为一组,实现在面积较大的住宅里,增强wifi覆盖范围,智能在多热点之间切换,提升上网体验。因为节点基本上在3个以内,所以mesh的算法不必太复杂,组网形式比较简单。各厂家都自定义了组_802.11s

线程的几种状态_线程状态-程序员宅基地

文章浏览阅读5.2k次,点赞8次,收藏21次。线程的几种状态_线程状态

stack的常见用法详解_stack函数用法-程序员宅基地

文章浏览阅读4.2w次,点赞124次,收藏688次。stack翻译为栈,是STL中实现的一个后进先出的容器。要使用 stack,应先添加头文件include<stack>,并在头文件下面加上“ using namespacestd;"1. stack的定义其定义的写法和其他STL容器相同, typename可以任意基本数据类型或容器:stack<typename> name;2. stack容器内元素的访问..._stack函数用法

2018.11.16javascript课上随笔(DOM)-程序员宅基地

文章浏览阅读71次。<li> <a href = "“#”>-</a></li><li>子节点:文本节点(回车),元素节点,文本节点。不同节点树:  节点(各种类型节点)childNodes:返回子节点的所有子节点的集合,包含任何类型、元素节点(元素类型节点):child。node.getAttribute(at...

随便推点

layui.extend的一点知识 第三方模块base 路径_layui extend-程序员宅基地

文章浏览阅读3.4k次。//config的设置是全局的layui.config({ base: '/res/js/' //假设这是你存放拓展模块的根目录}).extend({ //设定模块别名 mymod: 'mymod' //如果 mymod.js 是在根目录,也可以不用设定别名 ,mod1: 'admin/mod1' //相对于上述 base 目录的子目录}); //你也可以忽略 base 设定的根目录,直接在 extend 指定路径(主要:该功能为 layui 2.2.0 新增)layui.exten_layui extend

5G云计算:5G网络的分层思想_5g分层结构-程序员宅基地

文章浏览阅读3.2k次,点赞6次,收藏13次。分层思想分层思想分层思想-1分层思想-2分层思想-2OSI七层参考模型物理层和数据链路层物理层数据链路层网络层传输层会话层表示层应用层OSI七层模型的分层结构TCP/IP协议族的组成数据封装过程数据解封装过程PDU设备与层的对应关系各层通信分层思想分层思想-1在现实生活种,我们在喝牛奶时,未必了解他的生产过程,我们所接触的或许只是从超时购买牛奶。分层思想-2平时我们在网络时也未必知道数据的传输过程我们的所考虑的就是可以传就可以,不用管他时怎么传输的分层思想-2将复杂的流程分解为几个功能_5g分层结构

基于二值化图像转GCode的单向扫描实现-程序员宅基地

文章浏览阅读191次。在激光雕刻中,单向扫描(Unidirectional Scanning)是一种雕刻技术,其中激光头只在一个方向上移动,而不是来回移动。这种移动方式主要应用于通过激光逐行扫描图像表面的过程。具体而言,单向扫描的过程通常包括以下步骤:横向移动(X轴): 激光头沿X轴方向移动到图像的一侧。纵向移动(Y轴): 激光头沿Y轴方向开始逐行移动,刻蚀图像表面。这一过程是单向的,即在每一行上激光头只在一个方向上移动。返回横向移动: 一旦一行完成,激光头返回到图像的一侧,准备进行下一行的刻蚀。

算法随笔:强连通分量-程序员宅基地

文章浏览阅读577次。强连通:在有向图G中,如果两个点u和v是互相可达的,即从u出发可以到达v,从v出发也可以到达u,则成u和v是强连通的。强连通分量:如果一个有向图G不是强连通图,那么可以把它分成躲个子图,其中每个子图的内部是强连通的,而且这些子图已经扩展到最大,不能与子图外的任一点强连通,成这样的一个“极大连通”子图是G的一个强连通分量(SCC)。强连通分量的一些性质:(1)一个点必须有出度和入度,才会与其他点强连通。(2)把一个SCC从图中挖掉,不影响其他点的强连通性。_强连通分量

Django(2)|templates模板+静态资源目录static_django templates-程序员宅基地

文章浏览阅读3.9k次,点赞5次,收藏18次。在做web开发,要给用户提供一个页面,页面包括静态页面+数据,两者结合起来就是完整的可视化的页面,django的模板系统支持这种功能,首先需要写一个静态页面,然后通过python的模板语法将数据渲染上去。1.创建一个templates目录2.配置。_django templates

linux下的GPU测试软件,Ubuntu等Linux系统显卡性能测试软件 Unigine 3D-程序员宅基地

文章浏览阅读1.7k次。Ubuntu等Linux系统显卡性能测试软件 Unigine 3DUbuntu Intel显卡驱动安装,请参考:ATI和NVIDIA显卡请在软件和更新中的附加驱动中安装。 这里推荐: 运行后,F9就可评分,已测试显卡有K2000 2GB 900+分,GT330m 1GB 340+ 分,GT620 1GB 340+ 分,四代i5核显340+ 分,还有写博客的小盒子100+ 分。relaybot@re...

推荐文章

热门文章

相关标签