MySQL的 timze_zone 和 SpringBoot 的 serverTimezone 的设置

2023-11-15

查看和修改 MySQL 的时区

system_time_zone: 系统时区,
在MySQL启动时会检查当前系统的时区并根据系统时区设置全局参数system_time_zone的值。
system_time_zone 变量只有全局值没有会话值,不能动态修改,MySQL 启动时,将尝试自动确定服务器的时区,并使用它来设置 system_time_zone 系统变量, 此后该值不变。
	The system time zone. When the server starts, it attempts to determine the time zone of the host machine automatically and 
	uses it to set thesystem_time_zone system variable. The value does not change thereafter.

time_zone:
用来设置每个连接会话的时区,默认为 system 时,使用全局参数 system_time_zone 的值。
The current time zone. This variable is used to initialize the time zone for each client that connects. 
By default, the initial value of this is 'SYSTEM' (which means, “use the value of system_time_zone”).


--查看
mysql> show global variables like '%time%zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set (0.00 sec)

--修改全局时区,所有已经创建的、新创建的session都会被修改; 重启 mysql 服务就失效了
set global time_zone='+00:00';

--修改当前session的时区
set session time_zone='+00:00';

--方法2:在配置文件中添加,永久生效
[mysqld]
default-time-zone='+08:00'

把时区信息导入到了mysql库,导入方法:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -S /tmp/mysqld.sock mysql
时区影响了什么,概括一下就两点:
1. NOW() 和 CURTIME() 系统函数的返回值受当前 session 的时区影响
  不仅是select now(),包括insert .. values(now())、以及字段的 DEFAULT CURRENT_TIMESTAMP 属性也受此影响:
    mysql> set time_zone='+00:00';
	Query OK, 0 rows affected (0.00 sec)
	mysql> 
	mysql> select now(),CURTIME();
	+---------------------+-----------+
	| now()               | CURTIME() |
	+---------------------+-----------+
	| 2021-12-02 08:45:33 | 08:45:33  |
	+---------------------+-----------+
	1 row in set (0.00 sec)
	mysql> 
	mysql> set time_zone='+08:00';
	Query OK, 0 rows affected (0.00 sec)
	mysql> 
	mysql> select now(),CURTIME();
	+---------------------+-----------+
	| now()               | CURTIME() |
	+---------------------+-----------+
	| 2021-12-02 16:45:39 | 16:45:39  |
	+---------------------+-----------+
	1 row in set (0.00 sec)

2. timestamp 数据类型字段存储的数据受时区影响
   timestamp 数据类型会存储当时session的时区信息,读取时会根据当前 session 的时区进行转换;
   而 datetime 数据类型插入的是什么值,再读取就是什么值,不受时区影响。
   也可以理解为已经存储的数据是不会变的,只是 timestamp 类型数据在读取时会根据时区转换:

	mysql> set time_zone='+08:00';
	Query OK, 0 rows affected (0.00 sec)
	mysql> 
	mysql> create table t(ts timestamp, dt datetime);
	Query OK, 0 rows affected (0.02 sec)
	mysql> 
	mysql> insert into t values('2021-12-02 16:45:39','2021-12-02 16:45:39');
	Query OK, 1 row affected (0.00 sec)
	mysql> 
	mysql> select * from t;
	+---------------------+---------------------+
	| ts                  | dt                  |
	+---------------------+---------------------+
	| 2021-12-02 16:45:39 | 2021-12-02 16:45:39 |
	+---------------------+---------------------+
	1 row in set (0.00 sec)
	mysql> 
	mysql> set time_zone='+00:00';
	Query OK, 0 rows affected (0.00 sec)
	mysql> 
	mysql> select * from t;
	+---------------------+---------------------+
	| ts                  | dt                  |
	+---------------------+---------------------+
	| 2021-12-02 08:45:39 | 2021-12-02 16:45:39 |
	+---------------------+---------------------+
	1 row in set (0.00 sec)

Q:已经运行一段时间的业务,修改MySQL的时区会影响已经存储的时间类型数据吗?
A:完全不会,只会影响对 timestamp 数据类型的读取。这里不得不提一句,为啥要用 timestamp?
用 datetime 不香吗,范围更大,存储空间其实差别很小,赶紧加到开发规范中吧。

SpringBoot 应用:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver  // 需要使用高版本的驱动,否则下面的结论可能对不上
    url: jdbc:mysql://127.0.0.1:3306/flow_manager_dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true

或者

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver    // 或者使用低版本的驱动,但是 url 变量中需要增加 useTimezone=true
    url: jdbc:mysql://127.0.0.1:3306/flow_manager_dev?characterEncoding=utf-8&useSSL=false&useTimezone=true&serverTimezone=Asia/Shanghai&allowMultiQueries=true
  
useTimezone 参数来自搜索 mysql cst 时区: https://blog.csdn.net/m0_54849873/article/details/124336431

当创建数据时:

当在创建数据的时候, SpringBoot Java 代码可能是
  	app.setCreatedDate(new Date());  
  	appRepository.save(app);
  	
serverTimezone=Asia/Shanghai
    我们知道 new date() 返回的是带有应用服务器时区的时间比如 Thu Jun 15 14:03:47 CST 2023,
    而实际当写入数据库的时间也是 2023-06-15 14:03:47,(对应的记录是 app_code 为 StarDB_test1111111)
    这是因为上述数据库链接串中 serverTimezone=Asia/Shanghai,正好和应用服务器的本地时区一样

serverTimezone=UTC
    我们知道 new date() 返回的是带有应用服务器时区的时间比如 Thu Jun 15 14:11:18 CST 2023,
    而实际当写入数据库的时间也是 2023-06-15 06:11:18,(对应的记录是 app_code 为 StarDB_test_ServerTimeZoneUTC)
    这是因为上述数据库链接串中 serverTimezone=UTC,正好和应用服务器的本地时区差8个小时
    

数据库的时区信息和库表数据:
	mysql> show variables like "%time_zone%";
	+------------------+--------+
	| Variable_name    | Value  |
	+------------------+--------+
	| system_time_zone | CST    |
	| time_zone        | +04:00 |
	+------------------+--------+
	2 rows in set (0.00 sec)
	mysql>
	mysql> select id, uniq_id, app_code, creator, state,  created_datef, modified_date from app;
	+----+----------------------------------+-------------------------------+----------+-------+---------------------+---------------------+
	| id | uniq_id                          | app_code                      | creator  | state | created_date        | modified_date       |
	+----+----------------------------------+-------------------------------+----------+-------+---------------------+---------------------+
	|  1 | 14515ba1b56c785c98b36f6f6d509d85 | StarDB                        | robcheng |     1 | 2022-04-05 11:52:00 | 2022-06-06 17:46:52 |
	|  4 | ee4e0c109a88e98f25fd84e90ccca9c0 | DMS                           | robcheng |     1 | 2022-04-05 12:01:28 | 2022-05-05 19:43:45 |
	| 24 | 39831715f0c0258897d5997cfcf94b67 | StarDB_DEV                    | robcheng |     1 | 2022-05-18 14:33:40 | 2022-05-27 18:54:06 |
	| 46 | 788de6f75ea373b39651b69c796a8beb | StarDB_TEST                   | robcheng |     1 | 2022-05-27 18:56:05 | 2022-05-27 18:58:44 |
	| 47 | 5294688841174f05cfb2c355f6f91772 | StarDB_test11                 | robcheng |     1 | 2023-06-15 03:40:21 | 2023-06-15 03:40:21 |
	| 48 | 4655bdf331c58b7d1935d5aab7b8d9d7 | StarDB_test1111111            | robcheng |     1 | 2023-06-15 14:03:47 | 2023-06-15 06:03:47 |
	| 49 | c8be0df667dac57006b78298fae609cf | StarDB_test_NoServerTimeZone  | robcheng |     1 | 2023-06-15 06:08:12 | 2023-06-15 06:08:11 |
	| 50 | 8aad9fe2658f0e300b5d8db7faeb64e6 | StarDB_test_ServerTimeZoneUTC | robcheng |     1 | 2023-06-15 06:11:18 | 2023-06-15 06:11:18 |
	+----+----------------------------------+-------------------------------+----------+-------+---------------------+---------------------+
	8 rows in set (0.00 sec)
	mysql>
	mysql>

当获取数据列表时:

1. 当在获取列表时,实体专VO时,SpringBoot java 代码可能是
	List<AppVO> appVOList = appAssembler.entityToVoList(appList);

    以 app_code 为 StarDB_test1111111 的记录的创建时间: 2023-06-15 14:03:47 为例:
    serverTimezone=Asia/Shanghai
    	程序会把 2023-06-15 14:03:47,
    	当作是东八区(serverTimezone时区)的 2023-06-15 14:03:47, 
    	然后转换为应用服务区器所在的时区东八区的时间即 Thu Jun 15 14:03:47 CST 2023
        
    serverTimezone=UTC
    	程序会把 2023-06-15 14:03:47
    	当作是 UTC (serverTimezone时区)的 2023-06-15 14:03:47, 
    	然后转换为应用服务区器所在的时区东八区的时间即 Thu Jun 15 22:03:47 CST 2023   

Get 操作: serverTimezone=Asia/Shanghai
在这里插入图片描述
Get 操作: serverTimezone=UTC
在这里插入图片描述
2. 序列化 VO 返回给前端时

 API 返回前端的数据格式(即序列化时),会进一步经过 spring.jackson 配置的处理,
 猜测其处理过程是:把 VO 里的带时区的时间,转换为 spring.jackson.time-zone  spring.jackson.date-format 指定的时区和格式,返回前端。
 从结果上来看,就是把数据库中的创建时间列带着 spring.datasource.url 中的 serverTimezone 的时区,转换为  spring.jackson.time-zone  spring.jackson.date-format  的时区和格式返回给前端
 spring.jackson.time-zone  spring.jackson.date-format  的默认配置返回格式如下:

	 {
	    "result": [
	        ... ...
	        {
	            "uniqId": "4655bdf331c58b7d1935d5aab7b8d9d7",
	            "appCode": "StarDB_test1111111",
	            "appDesc": "This is a distributed databae",
	            "callbackUrl": "http://10.222.205.33:8030/o/executor/workflow",
	            "creator": "robcheng",
	            "createdDate": "2023-06-15T14:03:47.000+00:00",   ---------默认是标准的 UTC 时间格式---------
	            "modifiedDate": "2023-06-15T06:03:47.000+00:00"
	        },
	        ... ...
	    ],
	    "error": {
	        "code": 0,
	        "message": "",
	        "status": ""
	    },
	    "requestId": "1c9cf6f5-6d7c-4069-99ac-0fa2e65883af"
	}


spring:
  jackson:
	date-format: yyyy-MM-dd HH:mm:ss // 如果需要修改为UTC 可设置为 yyyy-MM-dd'T'HH:mm:ss'Z'
	time-zone: GMT+8

	{
	    "result": [
	        ... ...
	        {
	            "uniqId": "4655bdf331c58b7d1935d5aab7b8d9d7",
	            "appCode": "StarDB_test1111111",
	            "appDesc": "This is a distributed databae",
	            "callbackUrl": "http://10.222.205.33:8030/o/executor/workflow",
	            "creator": "robcheng",
	            "createdDate": "2023-06-15 22:03:47",  ---------spring.jackson.time-zone  spring.jackson.date-format 的时区和格式---------
	            "modifiedDate": "2023-06-15 14:03:47"
	        },
	        ... ...
	    ],
	    "error": {
	        "code": 0,
	        "message": "",
	        "status": ""
	    },
	    "requestId": "1c9cf6f5-6d7c-4069-99ac-0fa2e65883af"
	}

总结

serverTimeZone的作用就是指定web服务器和mysql服务器的会话期间的mysql服务器时区,就是临时指定mysql服务器的时区。

创建接口:从结果上来看,就是把应用服务器的 new Date() 转换成 spring.datasource.url 中的 serverTimezone 时区对应的 yyyy:mm:dd HH:MM:SS 格式的字符串保存到数据库里。

获取接口:从结果上来看,就是把数据库中的创建时间列带着 spring.datasource.url 中的 serverTimezone 时区,转换为 spring.jackson.time-zone spring.jackson.date-format 的时区和格式返回给前端

同理 golang 也有类似配置。

bean.DbEngine, err = utils.CreateOrmEngine(conf.DataBase.Account, conf.DataBase.Password, conf.DataBase.IP,
			conf.DataBase.Port, conf.DataBase.Schema, conf.DataBase.Charset, conf.DataBase.MaxIdle, conf.DataBase.MaxOpen)
// The following is VERY import for debug the datetime of mysql
// 在给创建时间赋值时,会把服务器所在时区的时间转换为 bean.DbEngine.DatabaseTZ 时区的时间保存;
// 而在获取数据时会把数据库里的创建时间当成  bean.DbEngine.DatabaseTZ 时区的,然后转换为 bean.DbEngine.TZLocation 时区的时间
bean.DbEngine.DatabaseTZ = time.UTC ,   
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL的 timze_zone 和 SpringBoot 的 serverTimezone 的设置 的相关文章

随机推荐

  • 第8章 【C语言】善于利用指针

    8 1 指针是什么 由于通过地址能找到所需的变量单元 可以说 地址指向该变量单元 将地址形象化称为 指针 直接按变量名进行的访问 称为 直接访问 方式 还可以采用另一种称为 间接访问 的方式 即将变量i的地址存放在另一变量中 然后通过该变量
  • Linux 运行Jar包命令

    一 后台运行jar nohup java jar home spring one demo 0 0 1 SNAPSHOT jar gt spring log 2 gt 1 nohup java jar admin jar gt gt noh
  • 【环境配置】Mac环境下利用Homebrew安装指定python版本

    文章目录 基础环境介绍 安装python3 9 配置快捷启动 基础环境介绍 Mac版本 macOS Monterey 12 6 终端环境 zsh 安装工具 homebrew 安装python3 9 使用home brew 安装指定版本pyt
  • 设置路由分发规则

    1 创建子路由 定义项目路由 设置路由参数 index应用配置 配置index应用的路由urls py 测试index应用的路由配置 访问http 127 0 0 1 8000
  • 一个45岁大爷第一天学习python的心得,现在开始还算晚吗

    写在前面的话 本人今年45岁了 初中文化 感觉都不好意思写出来 哈哈 之前没有学过编程方面的东西 前段时间在头条上看到潘石圪在学习python编程 于是从各方面去了解了一下python到底是个什么 赶紧找了一下度娘 不看不知道 一看吓一跳啊
  • ubuntu提示根目录存储空间不足的解决办法

    因为每次使用系统都会产生大量的日志文件 如果没有设置自动清理日志文件或者分区较小 日志文件在一段时间的堆积后就会导致存储空间不足 所以需要清除日志文件 以下是清除步骤 1 切换为超级用户 su 2 查看日志文件大小 du h max dep
  • 【Windows】win10电脑Miracast投屏到电视

    Miracast 是一项无线技术 你的电脑可以使用它来将你的屏幕投影到电视 投影仪和同样支持 Miracast 的流媒体播放器 你可以使用此技术共享你在电脑上执行的操作 展示幻灯片放映 甚至在更大的屏幕上玩你喜爱的游戏 为你的设备做好准备
  • 目前最受欢迎的12个Python开源框架,你用过几个?

    今天给大家带来了12个在GitHub等开源网站中最受欢迎的Python开源框架 如果你正在学习python 那么这12个开源框架 千万别错过 这些框架包括事件I O OLAP Web开发 高性能网络通信 测试 爬虫等 虽说不上是全都有 但也
  • UE4 导航网格的使用

    在使用导航网格前 应先设置项目导航系统支持的导航代理者 Agents 在项目设置中 找到导航系统页面 DirtyAreasUpdateFreq 表示导航网格变化时 检测变化并更新的频率 这里可以设置导航系统的一些参数 包括是否允许客户端导航
  • DT下重新定义设置发布发布条数后的跳转页面

    destoon系统有些地方还是做得不够细致 今天给大家分享一个重新定义发布条数满了以后的页面跳转 正常逻辑跳转应该是会员升级页面而不是会员中心首页 修改方法如下 感谢DT朋友提供的修改方案 打开根目录文件 module article my
  • el-tree 阻止点击节点的时候自动展开或者收缩

    expand on click node 是否在点击节点的时候展开或者收缩节点 默认值为 true 如果为 false 则只有点箭头图标的时候才会展开或者收缩节点 但设置的时候 要加上 不然无效
  • 点选文字验证码识别

    最近在学习爬虫 碰到很多验证登录 今天分享一个点选文字验证码识别以及我在使用的验证码识别平台 上篇文章有涉及滑块验证 首先 注册一个超级鹰账号 选择充值0 5 1元即可 进入用户中心 gt 软件ID 生成一个用来接入接口的软件ID 下载示例
  • Acwing-二叉树的镜像

    遍历树中的所有点 每次遍历完之后把左右儿子swap一下 Definition for a binary tree node struct TreeNode int val TreeNode left TreeNode right TreeN
  • 线程池七大参数

    线程池的七大参数是指使用 ThreadPoolExecutor 创建线程池时所设置的 7 个参数 分别为 public ThreadPoolExecutor int corePoolSize int maximumPoolSize long
  • VScode for c++

    VScode for c VScode for c launch json version 0 2 0 configurations name gdb Launch type cppdbg request launch program wo
  • java集合之Map

    java集合之Map Map接口概述 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 Map接口和Collection接口的不同 Map是双列的 Collection是单列的 Map的键唯一 Collection的
  • Linux Rsync服务详解(二)——Rsync服务实战

    今天继续给大家介绍Linux运维相关内容 本文主要内容是Rsync服务详解 一 Rsync实战 接下来 我们选择使用两台设备进行Rysnc的备份实战 设备一IP地址 192 168 136 101 设备二IP地址 192 168 136 2
  • 【openGL2021版】天空盒

    openGL2021版 天空盒 大家好 我是Lampard猿奋 欢迎来到船新的openGL基础系列的博客 今天主要实现的是天空盒 1 什么是天空盒 上周我们已经实现了FPS式的摄像机控制 键盘的 WSAD 可以控制摄像头的前后左右移动 鼠标
  • FPGA面试题【Verilog实现一个2位带进位全加器,画出门级电路】

    目录 题目 核心思路 答案 FPGA全貌 题目 Verilog实现一个2位带进位全加器 画出门级电路 核心思路 思路见代码注释 答案 2位加法器顶层模块 module top s cout a b cin 输入输出端口及变量定义 outpu
  • MySQL的 timze_zone 和 SpringBoot 的 serverTimezone 的设置

    查看和修改 MySQL 的时区 system time zone 系统时区 在MySQL启动时会检查当前系统的时区并根据系统时区设置全局参数system time zone的值 system time zone 变量只有全局值没有会话值 不