前言:

在使用 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时区相关问题的资料请关注脚本之家其它相关文章!

mysql 创建表指定时区_mysql解决时区相关问题相关推荐

  1. dos窗口mysql创建数据库指定字符集_MySQL数据库 dos 命令窗口命令集

    一.DDL:数据库定义语言 数据库的操作:(操作关键字不分大小写) create database day01;//创建数据库 show databases;//查看该帐号下的所有数据库 show c ...

  2. mysql 创建表主键_MySQL创建表和主键约束

    1.创建表 在操作数据表之前,应该使用"USE 数据库名"指定操作是在哪个数据库中进行 主键约束(唯一标识) ****非空*** ****唯一*** ****被引用****(学习外 ...

  3. mysql 创建表普通索引_MySQL索引篇,创建表时创建索引

    索引对于MySQL数据库查询速度具有无可取代的作用,一个合适的索引能给数据查询的效率带来巨大的提升,本文来给大家讲讲如何创建索引,索引的最佳创建方式是在建表的时候就确定好要索引的字段并建立好索引. 索 ...

  4. mysql创建表的默认大小_mysql InnoDB建表时设定初始大小的方法

    InnoDB在写密集的压力时,由于B-Tree扩展,因而也会带来数据文件的扩展,然而,InnoDB数据文件扩展需要使用mutex保护数据文件,这就会导致波动. 丁奇的博客说明了这个问题: When I ...

  5. mysql创建表并指定字符集_mysql 创建表 指定字符集

    不知道你是不是想像下面那样作转换: CREATE TABLE `books` ( `id` varchar(8) NOT NULL default '', `name` varchar(24) def ...

  6. mysql创建表的时候日期给个默认值_mysql 创建表时 日期字段默认值为当前时间...

    mysql 创建表时 日期字段默认值为当前时间 mysql version 5.1 在mysql创建表的时候经常会遇到创建日期字段需要设置当前时间为默认值的时候,就如sqlserver2000一样,把 ...

  7. mysql创建表有则删除_MySQL创建表和删除表

    创建表 简单的方式 CREATE TABLE person ( number INT(11), name VARCHAR(255), birthday DATE ); 或者是 CREATE TABLE ...

  8. mysql创建表时设置外键_mysql创建表时设置外键约束的方法

    mysql创建表时设置外键约束的方法 发布时间:2020-06-17 15:54:11 来源:亿速云 阅读:312 作者:元一 MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中, ...

  9. mysql创建表设置自增_mysql 创建表并设置主键自增

    mysql 创建表并设置主键自增 mysql 创建表: mysql> create table user( -> userid int(4) primary key not null au ...

  10. oracle与mysql创建表时的区别

    oracle创建表时,不支持在建表时同时增加字段注释.故采用以下方式: #创建表 CREATE TABLE predict_data as (id integer NOT NULL, uid varc ...

最新文章

  1. enumerate在python中的意思_Python中enumerate用法详解
  2. Cocos2d-x win7 + vs2010 配置图文详解 .
  3. JDBC读取新插入Oracle数据库Sequence值的5种方法
  4. js字符串的操作方法
  5. Python开发者的完美终端工具
  6. 此 sqltransaction 已完成;它再也无法使用_手把手教你如何修眉毛,学会再也不用花钱去美容院了...
  7. 52linux crond入门53crond时间规则54应用实例
  8. fastjson xml转json_在XML中测试Fastjson反序列化
  9. aspnet实现搜索查询_C#算法设计查找篇之01-顺序查找
  10. python访问字符串中的部分字符的操作_python中字符串的常见操作方法
  11. cocos2d-x学习记录3——CCTouch触摸响应
  12. Vue:vue中使用layUI
  13. 软件测试技术体系-专业术语
  14. 查看手机db数据库文件
  15. 电厂的计算机人员职位结构简图,我们电厂汽轮机结构示意图(老师傅整理)
  16. 红旗Linux中文教程
  17. Win7 关闭触摸屏 屏幕键盘功能
  18. 2021年,到底该不该去培训机构!<仅供参考,因人而异!>
  19. 计算机部分应用显示模糊,win10系统打开部分软件字体总显示模糊的解决方法-电脑自学网...
  20. bzoj5369: [PKUSC2018]最大前缀和 (状压dp)

热门文章

  1. AttributeError: ‘str‘ object has no attribute ‘spilt‘ on line 9
  2. 微信小程序,仓库系统,可以扫描入库查询
  3. Java打造RPC框架(四):支持zookeeper与负载均衡
  4. 华为人均工资70万人人想要,可华为员工16项标准你能做到几条?
  5. 支付接口的API什么?SDK是什么?
  6. 易语言-post登陆百度
  7. matlab爆炸建模,7.2.5萨墓基尔加丹M螺旋爆炸技能建模分析
  8. 原来《羊了个羊》也求助了云,拦截bot自动化攻击达5000万次 | CCF C³
  9. workman定时任务队列雏形
  10. markdown转html格式