解决时区报错The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone.

好久没接触后端,今天连接数据库出现了个很熟悉的问题,时区设置报错了,但是以前都是直接搜的解决办法,CV一下就解决了,一直都没有思考过这个报错的原因,然后今天刚好看到一篇很好的文章,就记录下来了。文章链接在文章末尾附上。

The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. 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 '配置属性)来使用更具体的时区值。

一、问题发生

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

使用mybatis-plus生成代码的时候,尝试连接数据库出现了这个报错问题。在项目中只要涉及到连接数据库,都有可能会遇到这个时区错误的问题。

这个问题是由于数据库服务器的时区设置不正确导致的。需要在数据库服务器或JDBC驱动程序中配置一个更具体的时区值,以便使用时区支持。

二、 问题解决

解决方法:

  1. 检查数据库服务器的时区设置,确保它是正确的。可以查看数据库服务器的文档或联系数据库管理员来获取正确的时区值。
  2. 如果使用的是MySQL数据库,可以在连接字符串中添加serverTimezone参数来指定时区。例如:
    ?serverTimezone=Asia/Shanghai
  3. 降低使用的数据库版本。由于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分。

参考文章链接:The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone_明月几时有666-CSDN开发云

 如有侵权请联系删除。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值