前言:

在使用MySQL的过程中,你可能会遇到时区相关问题,比如说时间显示错误、时区不是东八区、程序取得的时间和数据库存储的时间不一致等等问题。其实,这些问题都与数据库时区设置有关,本篇文章将从数据库参数入手,逐步介绍时区相关内容。

1.log_timestamps参数介绍

首先说明下log_timestamps参数并不影响时区,只是设置不同会影响某些日志记录的时间。该参数主要是控制 error log、slow log、genera log 日志文件中的显示时间,但不会影响 general log 和 slow log 写到表 (mysql.general_log, mysql.slow_log) 中的显示时间。

log_timestamps是全局参数,可动态修改,默认使用UTC时区,这样会使得日志中记录的时间比北京时间慢8个小时,导致查看日志不方便。可以修改为SYSTEM变成使用系统时区。下面简单测试下该参数的作用及修改方法:

# 查看参数值

mysql> show global variables like 'log_timestamps';

+----------------+-------+

| Variable_name | Value |

+----------------+-------+

| log_timestamps | UTC |

+----------------+-------+

1 row in set (0.00 sec)

# 产生慢日志

mysql> select sleep(10),now();

+-----------+---------------------+

| sleep(10) | now() |

+-----------+---------------------+

| 0 | 2020-06-24 17:12:40 |

+-----------+---------------------+

1 row in set (10.00 sec)

# 慢日志文件记录内容 发现时间是UTC时间

# Time: 2020-06-24T09:12:50.555348Z

# User@Host: root[root] @ localhost [] Id: 10

# Query_time: 10.000354 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1

SET timestamp=1592989960;

select sleep(10),now();

# 修改参数值 再次测试

mysql> set global log_timestamps = SYSTEM;

Query OK, 0 rows affected (0.00 sec)

mysql> select sleep(10),now();

+-----------+---------------------+

| sleep(10) | now() |

+-----------+---------------------+

| 0 | 2020-06-24 17:13:44 |

+-----------+---------------------+

1 row in set (10.00 sec)

# 慢日志文件记录内容 时间是对的

# Time: 2020-06-24T17:13:54.514413+08:00

# User@Host: root[root] @ localhost [] Id: 10

# Query_time: 10.000214 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1

SET timestamp=1592990024;

select sleep(10),now();

2.time_zone参数介绍

time_zone参数用来设置每个连接会话的时区,该参数分为全局和会话级别,可以动态修改。默认值为SYSTEM,此时使用的是全局参数system_time_zone的值,而system_time_zone默认继承自当前系统的时区,即默认情况下MySQL时区和系统时区相同。

时区设置主要影响时区敏感的时间值的显示和存储。包括一些函数(如now()、curtime())显示的值,以及存储在TIMESTAMP类型中的值,但不影响DATE、TIME和DATETIME列中的值,因为这些数据类型在存取时未进行时区转换,而TIMESTAMP类型存入数据库的实际是UTC的时间,查询显示时会根据具体的时区来显示不同的时间。

下面我们来测试下time_zone参数修改产生的影响:

# 查看linux系统时间及时区

[root@centos ~]# date

Sun Jun 28 14:29:10 CST 2020

# 查看MySQL当前时区、时间

mysql> show global variables like '%time_zone%';

+------------------+--------+

| Variable_name | Value |

+------------------+--------+

| system_time_zone | CST |

| time_zone | SYSTEM |

+------------------+--------+

2 rows in set (0.00 sec)

mysql> select now();

+---------------------+

| now() |

+---------------------+

| 2020-06-28 14:31:12 |

+---------------------+

1 row in set (0.00 sec)

# 创建测试表、插入部分数据

mysql> CREATE TABLE `time_zone_test` (

-> `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',

-> `dt_col` datetime DEFAULT NULL COMMENT 'datetime时间',

-> `ts_col` timestamp DEFAULT NULL COMMENT 'timestamp时间',

-> PRIMARY KEY (`id`)

-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='time_zone测试表';

Query OK, 0 rows affected, 1 warning (0.07 sec)

mysql> insert into time_zone_test (dt_col,ts_col) values ('2020-06-01 17:30:00','2020-06-01 17:30:00'),(now(),now());

Query OK, 2 rows affected (0.01 sec)

Records: 2 Duplicates: 0 Warnings: 0

mysql> select * from time_zone_test;

+----+---------------------+---------------------+

| id | dt_col | ts_col |

+----+---------------------+---------------------+

| 1 | 2020-06-01 17:30:00 | 2020-06-01 17:30:00 |

| 2 | 2020-06-28 14:34:55 | 2020-06-28 14:34:55 |

+----+---------------------+---------------------+

# 改为UTC时区 并重新连接 发现timestamp存储的时间会随时区变化

mysql> set global time_zone='+0:00';

Query OK, 0 rows affected (0.00 sec)

mysql> set time_zone='+0:00';

Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like '%time_zone%';

+------------------+--------+

| Variable_name | Value |

+------------------+--------+

| system_time_zone | CST |

| time_zone | +00:00 |

+------------------+--------+

2 rows in set (0.00 sec)

mysql> select now();

+---------------------+

| now() |

+---------------------+

| 2020-06-28 06:36:16 |

+---------------------+

1 row in set (0.00 sec)

mysql> select * from time_zone_test;

+----+---------------------+---------------------+

| id | dt_col | ts_col |

+----+---------------------+---------------------+

| 1 | 2020-06-01 17:30:00 | 2020-06-01 09:30:00 |

| 2 | 2020-06-28 14:34:55 | 2020-06-28 06:34:55 |

+----+---------------------+---------------------+

2 rows in set (0.00 sec)

# 改回东八时区,恢复正常

mysql> set global time_zone='+8:00';

Query OK, 0 rows affected (0.00 sec)

mysql> set time_zone='+8:00';

Query OK, 0 rows affected (0.00 sec)

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)

mysql> select now();

+---------------------+

| now() |

+---------------------+

| 2020-06-28 14:39:14 |

+---------------------+

1 row in set (0.00 sec)

mysql> select * from time_zone_test;

+----+---------------------+---------------------+

| id | dt_col | ts_col |

+----+---------------------+---------------------+

| 1 | 2020-06-01 17:30:00 | 2020-06-01 17:30:00 |

| 2 | 2020-06-28 14:34:55 | 2020-06-28 14:34:55 |

+----+---------------------+---------------------+

2 rows in set (0.00 sec)

如果需要永久生效,还需写入配置文件中。例如将时区改为东八区,则需要在配置文件[mysqld]部分增加一行:default_time_zone = '+8:00'。

3.时区常见问题及如何避免

时区设置不妥可能会产生各种问题,下面我们列举下几个常见的问题及解决方法:

3.1 MySQL内部时间不是北京时间

遇到这类问题,首先检查下系统时间及时区是否正确,然后看下MySQL的time_zone,建议将time_zone改为'+8:00'。

3.2 Java程序存取的时间与数据库中的时间相差8小时

出现此问题的原因大概率是程序时区与数据库时区不一致导致的。我们可以检查下两边的时区,如果想统一采用北京时间,则可以在jdbc连接串中增加 serverTimezone=Asia/Shanghai,并且MySQL方面也可以将time_zone改为'+8:00'。

3.3 程序时间与数据库时间相差13小时或14小时

如果说相差8小时不够让人惊讶,那相差13小时可能会让很多人摸不着头脑。出现这个问题的原因是JDBC与MySQL对 “CST” 时区协商不一致。因为CST时区是一个很混乱的时区,有四种含义:

美国中部时间 Central Standard Time (USA) UTC-05:00或UTC-06:00

澳大利亚中部时间 Central Standard Time (Australia) UTC+09:30

中国标准时 China Standard Time UTC+08:00

古巴标准时 Cuba Standard Time UTC-04:00

MySQL中,如果time_zone为默认的SYSTEM值,则时区会继承为系统时区CST,MySQL内部将其认为是UTC+08:00。而jdbc会将CST认为是美国中部时间,这就导致会相差13小时,如果处在冬令时还会相差14个小时。

解决此问题的方法也很简单,我们可以明确指定MySQL数据库的时区,不使用引发误解的CST,可以将time_zone改为'+8:00',同时jdbc连接串中也可以增加serverTimezone=Asia/Shanghai。

3.4 如何避免出现时区问题

如何避免上述时区问题,可能你心里也有了些方法,简要总结几点如下:

首先保证系统时区准确。

jdbc连接串中指定时区,并与数据库时区一致。

time_zone参数建议设置为'+8:00',不使用容易误解的CST。

各环境数据库实例时区参数保持相同。

可能有的同学说了,我们数据库中time_zone参数选择的是默认的SYSTEM值,也没有发生程序时间和数据库时间不一致的问题。此时是否需要将time_zone改为'+8:00'?在这种情况下还是建议将time_zone改为'+8:00',特别是经常查询TIMESTAMP字段,因为当time_zone=system的时候,查询timestamp字段会调用系统的时区做时区转换,有全局锁__libc_lock_lock的保护,可能导致线程并发环境下系统性能受限。而改为'+8:00'则不会触发系统时区转换,使用MySQL自身转换,大大提高了性能。

总结:

读完本篇文章,你是否对数据库时区有了更深刻的认识呢。希望这篇文章对你有所帮助,特别是想了解MySQL时区相关内容时,可以拿来多读读。如果你遇到过其他时区相关问题,欢迎留言讨论。

mysql时区作用_一文解决MySQL时区相关问题相关推荐

  1. mysql内部时区_一文解决MySQL时区相关问题

    前言: 在使用MySQL的过程中,你可能会遇到时区相关问题,比如说时间显示错误.时区不是东八区.程序取得的时间和数据库存储的时间不一致等等问题.其实,这些问题都与数据库时区设置有关,本篇文章将从数据库 ...

  2. mysql 1032错误_如何快速解决MySQL 1032 主从错误

    3分钟解决MySQL 1032主从错误 Part1:写在最前 1032错误----现在生产库中好多数据,在从库误删了,生产库更新后找不到了,现在主从不同步了,再跳过错误也没用,因为没这条,再更新还会报 ...

  3. mysql数据库访问控制_一文总结MySQL数据库访问控制实现原理

    MySQL 访问控制实际上由两个功能模块共同组成,一个是负责"看守 MySQL 大门"的用户管理模块,另一个就是负责监控来访者每一个动作的访问控制模块.用户管理模块决定用户是否能登 ...

  4. mysql 的事件_一文总结MySQL数据库事件--定时任务实现方式

    由于最近在做某些日志表的清理工作,会用到定时任务,所以这里也简单介绍一下mysql如何用事件来实现定时任务. 后面会介绍两个日志表清理实现方案,一种是传统的定时delete,另一种会稍微复杂点,主要是 ...

  5. 一文解决MySQL时区相关问题

    https://zhuanlan.zhihu.com/p/154109590 前言: 在使用 MySQL 的过程中,你可能会遇到时区相关问题,比如说时间显示错误.时区不是东八区.程序取得的时间和数据库 ...

  6. django2.1支持的mysql版本_一文解决django 2.2与mysql兼容性问题

    Django是一个开放源代码的Web应用框架,由Python写成.采用了MTV的框架模式,即模型M,视图V和模版T.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS( ...

  7. npm mysql 事务_一文解读MySQL事务

    经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下. MySQL 事务 本文所说的 MySQL 事务都是指在 I ...

  8. mysql隐藏用户名_系统默认的MySQL用户名消失的解决方法(修正版)

    修改MySQL下的默认mysql数据库的user表,删除所有host为localhost记录,另 外添加一些其他记录,重新启动MySQL服务器.执行show databases,只出现informat ...

  9. 易语言mysql乱码_分享一个解决MySQL写入中文乱码的方法

    [编程语言:易语言] 之前有发帖请教过如何解决MySQL写入中文乱码的问题.但没人会,或者是会的人不想回答.搜索网上的答案并尝试很多次无效,所以当时就因为这个乱码问题搁浅了一个软件很多日子. 直到昨天 ...

  10. mysql断电同步不起作用_记一次mysql主从同步因断电产生的不能同步问题 1236 and 1032...

    背景: 项目新上线一个月,qa需要测试断电服务拉起,服务拉起成功后,发现mysql主从异常 以下是发现的问题以及解决方案 问题1: Slave_IO_Running:  No 一方面原因是因为网络通信 ...

最新文章

  1. 目标检测 - 如何在图片中标记Annotations中的坐标信息?
  2. 【car】购买新能源电动汽车的几个注意事项
  3. 20145231第四周学习笔记
  4. 某虚拟化项目总结:一条光纤引发的故障
  5. 分别求两个整数的最大公约数和最小公倍数。_看不懂辗转相除法求最小公约数?以身相许那种哦!...
  6. Retrofit+Rxjava+OkHttp
  7. MySQL索引常用算法
  8. beeline安装_hive使用beeline配置远程连接
  9. 2021年中国电缆吹风机市场趋势报告、技术动态创新及2027年市场预测
  10. 888. 公平的糖果棒交换
  11. 基于SSH的电子政务系统(附论文)
  12. Jeff Dean的神话
  13. 梁宁-产品思维30讲-痛点、爽点和痒点都是产品机会
  14. HDU 3966 Aragorns Story
  15. 数据库中什么是候选码,主码,主属性和非主属性
  16. 支付宝app支付功能-服务端的实现-python3版
  17. shineblink 紫外线测量
  18. VBA 模块级变量和过程级变量,全局变量,局部变量,end,exit end sub等影响
  19. 计算机与数学交融的教学设计,信息技术与小学数学学科的整合 小学数学教案...
  20. 账单管理系统(SpringCloud)

热门文章

  1. HDU-1548 A strange lift
  2. HTML实现3D图片旋转效果
  3. Python数据爬虫学习笔记(19)Scrapy天善智能网课信息爬虫
  4. Sumatra PDF阅读器之 Sumatra PDF 高级设置
  5. 69 MyBatis和Spring整合
  6. idea 报错improperly specified vm option. to fix the problem,edit your jvm option and remove the option
  7. mac ruby 环境变量_Ruby环境设置| 在Mac和Windows操作系统上安装Ruby
  8. Web基础(从零开始)——HTML文本域(textarea标签)
  9. lmp91000偏压配置求助
  10. 【复数表达】Deep Complex Network