跳到主要内容

mysql 时区问题

2023-05-30

基本流程

个人大概的理解如下, 至于细节需要反复查看文档才能确认.

首先需要理解的是, 时区问题是为了解决存储local datetime数据才引入的问题, 如果全局都保存为epoch timestamp long 字段, 就没有这类问题需要处理了, 也就摆脱了这类烦心事.

  • 上传数据: 客户端连接的时候是有时区信息的, 默认是本地mysql client机器上的时区, 要么是数据库连接字符串上的时区信息, 于是看起来无时区的local datetime, 在上传保存到服务器仍然是有时区信息的.

  • 存储数据: mysql server服务端存储的local datetime会根据mysql server的时区进行转换, 默认取决于安装所在的操作系统时区(system 时区), 或者直接在my.cnf上进行配置.

  • 查看数据: 在客户端查询数据的时候, 也会根据本地时区或是连接串的时区信息进行展示, 因此shell上看到的时间信息已经是通过时区转换的了.

问题出来了, 如果服务器的数据进行了跨操作系统迁移, 或者客户端连接串里的时区信息出现错误, 最终客户交互侧就是一团乱. 直接使用绝对时间戳, 就可以不用再纠结这些细节了.

咨询chatgpt

由于自己有大概的了解, chatgpt这段解释看起来可信度就非常高了

picture 1

picture 2

CST 代表什么时区

有些问题去问chatgpt, 一质问他就换另一种结果, 最后问完也不能确认到底对不对

picture 3

这时候还不如问他有什么办法可以去确认, 然后按照方法执行就可以了, 授人以鱼不如授人以渔, 自己测试反而靠谱了许多.

picture 4

要验证的话需要确保当前的session timezone使用的是system时区, 然后再执行now进行查询.

经过测试, mysql查询timezone返回的cst代表了中国时区.


MariaDB [(none)]> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> SELECT @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| CST |
+--------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2023-06-04 15:37:19 |
+---------------------+
1 row in set (0.000 sec)

基本操作

MySQL Time Zones

https://stackoverflow.com/questions/9808160/mysql-time-zones

  • 启动mysql server时可以配置时区

MySQL's default timezone variable can be initialised to a different value at start-up by providing the following command line option:

--default-time-zone=timezone

  • 超级管理员支持runtime设置全局时区

f you are a MySQL SUPER user, you can set the SYSTEM time_zone variable at runtime from the MYSQL> prompt using the following syntax:

SET GLOBAL time_zone=timezone;
  • 每个session支持设置时区

MySQL also supports individual SESSION timezone values which defaults to the GLOBAL time_zone environment variable value. To change the session timezone value during a SESSION, use the following syntax:

SET time_zone=timezone;
  • 查看全局mysql时区与当前连接进程的时区
SELECT @@global.time_zone, @@session.time_zone;