MySQL中时区参数time_zone解读

 更新时间:2025年01月22日 15:29:29   作者:Bing@DBA  
MySQL时区参数time_zone用于控制系统函数和字段的DEFAULT CURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型的值,建议在MySQL配置文件中设置时区参数,以确保高并发时的性能,在业务中尽量使用datetime类型来存储时间,因为其时间上限比TIMESTAMP更远

前言

MySQL 时区参数 time_zone 有什么用?修改它有什么影响?

如何设置该参数,本篇文章会详细介绍。

1.时区参数影响

time_zone 参数影响着 MySQL 系统函数还有字段的 DEFAULT CURRENT_TIMESTAMP 的属性。

查询当前的时区,+8:00 就代表国内的时区:

root@mysql 15:08:  [(none)]>select @@time_zone;
+-------------+
| @@time_zone |
+-------------+
| +08:00      |
+-------------+

查询当前时间:

root@mysql 15:09:  [(none)]>select now();
+---------------------+
| now()               |
+---------------------+
| 2024-12-12 15:09:44 |
+---------------------+

修改时区,为 UTC -8:00 美国时间:

root@mysql 15:09:  [(none)]>set global time_zone = '-08:00';
Query OK, 0 rows affected (0.00 sec)

查询当前时间:

root@mysql 15:09:  [(none)]>select now();
+---------------------+
| now()               |
+---------------------+
| 2024-12-11 23:09:55 |
+---------------------+

另外,需要注意的是 timestamp 类型,会随着 time_zone 的值产生变化,而 datetime 类型则不会,请看下方演示。

确认当前 time_zone 参数值:

select @@time_zone;

+-------------+
| @@time_zone |
+-------------+
| +08:00      |
+-------------+

创建测试表结构,两张表的区别是 created_at、updated_at 分别为 datetime 和 timestamp 类型。

CREATE TABLE `api_datetime` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  user varchar(10),
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `enabled` bit(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;


CREATE TABLE `api_timestamp` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  user varchar(10),
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `enabled` bit(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

模拟数据插入:

insert into api_timestamp(user, enabled) values ('+08:00', b'1');
insert into api_datetime(user, enabled) values ('+08:00', b'1');

查询表数据:

root@mysql 16:21:  [test]>select user,created_at, updated_at from api_datetime;
+--------+---------------------+---------------------+
| user   | created_at          | updated_at          |
+--------+---------------------+---------------------+
| +08:00 | 2024-12-12 16:20:34 | 2024-12-12 16:20:34 |
+--------+---------------------+---------------------+
1 row in set (0.00 sec)

root@mysql 16:21:  [test]>select user,created_at, updated_at from api_timestamp;
+--------+---------------------+---------------------+
| user   | created_at          | updated_at          |
+--------+---------------------+---------------------+
| +08:00 | 2024-12-12 16:20:33 | 2024-12-12 16:20:33 |
+--------+---------------------+---------------------+

修改 time_zone 参数值,为 -8:00:

set global time_zone = '-8:00';

插入测试数据:

insert into api_timestamp(user, enabled) values ('-08:00', b'1');
insert into api_datetime(user, enabled) values ('-08:00', b'1');
root@mysql 16:25:  [test]>select user,created_at, updated_at from api_datetime;
+--------+---------------------+---------------------+
| user   | created_at          | updated_at          |
+--------+---------------------+---------------------+
| +08:00 | 2024-12-12 16:20:34 | 2024-12-12 16:20:34 |
| -08:00 | 2024-12-12 00:25:52 | 2024-12-12 00:25:52 |
+--------+---------------------+---------------------+
2 rows in set (0.00 sec)

root@mysql 16:25:  [test]>select user,created_at, updated_at from api_timestamp;
+--------+---------------------+---------------------+
| user   | created_at          | updated_at          |
+--------+---------------------+---------------------+
| +08:00 | 2024-12-12 00:20:33 | 2024-12-12 00:20:33 |
| -08:00 | 2024-12-12 00:25:52 | 2024-12-12 00:25:52 |
+--------+---------------------+---------------------+
2 rows in set (0.00 sec)

由上方测试,我们发现如果字段设置为 CURRENT_TIMESTAMP 无论是 datetime 还是 timestamp 类型,都会随 time_zone 参数影响,不过 datetime 类型的历史数据不会受影响,timestamp 类型的历史数据,会随着 time_zone 的调整而发生变化。

2.如何设置

推荐直接写在 MySQL 的配置文件中,需要重启生效。

[mysqld]
default-time-zone='+08:00'

该参数默认为 SYSTEM 表示该参数值,取自操作系统的时区设置。不过还是建议在 MySQL 参数文件中设置一下,因为操作系统可能可能不完全归 DBA 管理,万一有人突然调整了,可能会引起线上问题。

另外,如果 time_zone 使用默认的 system 值,表示默认使用操作系统的时区,则每次通过时区计算时间时,要调用操作系统底层系统函数 __tz_convert(),而这个函数需要额外的加锁操作,以确保这时操作系统时区没有修改。高并发的时候会导致 TIMESTAMP 类型的表和操作,性能降低。

3.字段类型选择

业务中尽量使用 datetime 类型来存储时间,除了历史数据不会随着时区发生变化外,还有一个最大值限制问题。

TIMESTAMP 存储的是 1970-01-01 00:00:00’ 到现在的毫秒数,TIMESTAMP 占用 4 个字节,因此其存储的时间上限只能到 2038-01-19 03:14:07 已经离现在不远了,是需要重视的,业务又将面临一次类似千年虫的问题。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MySQL之修改数据表存储引擎的三种方式

    MySQL之修改数据表存储引擎的三种方式

    这篇文章主要介绍了MySQL之修改数据表存储引擎的三种方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • SQL和NoSQL之间的区别总结

    SQL和NoSQL之间的区别总结

    在本篇内容里我们给大家精选了关于SQL和NoSQL之间的区别的总结内容,对此有需要的朋友们跟着学习下。
    2019-02-02
  • insert...on duplicate key update语法详解

    insert...on duplicate key update语法详解

    本文主要介绍了insert...on duplicate key update语法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • MySQL获取系统性能和状态代码

    MySQL获取系统性能和状态代码

    使用MySQL获取系统性能和状态的代码片段,由此需求的朋友可以参考下,希望对大家有所帮助
    2013-07-07
  • MySQL DBA 常用手册小结

    MySQL DBA 常用手册小结

    MySQL DBA 常用手册小结,使用mysql的朋友可以参考下。
    2011-11-11
  • 使用MySQL的LAST_INSERT_ID来确定各分表的唯一ID值

    使用MySQL的LAST_INSERT_ID来确定各分表的唯一ID值

    MySQL数据表结构中,一般情况下,都会定义一个具有‘AUTO_INCREMENT’扩展属性的‘ID’字段,以确保数据表的每一条记录都可以用这个ID唯一确定
    2011-08-08
  • mysql分区表的增删改查的实现示例

    mysql分区表的增删改查的实现示例

    增删查改在数据库中是很常见的操作,本文主要介绍了mysql分区表的增删改查的实现示例,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-01-01
  • windows下mysql中binlog日志分析和数据恢复问题

    windows下mysql中binlog日志分析和数据恢复问题

    这篇文章主要介绍了windows下mysql中binlog日志分析和数据恢复问题,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • MYSQL数据库Innodb 引擎mvcc锁实现原理

    MYSQL数据库Innodb 引擎mvcc锁实现原理

    这篇文章主要介绍了MYSQL数据库Innodb 引擎mvcc锁实现原理,但是mvcc 的实现原理是什么呢?下文我们就来实例说明来mvcc 的实现原理,感兴趣的小伙伴可以参考一下
    2022-05-05
  • 浅析Mysql Join语法以及性能优化

    浅析Mysql Join语法以及性能优化

    在讲MySQL的Join语法前还是先回顾一下联结的语法,呵呵,其实连我自己都忘得差不多了,那就大家一起温习吧,这里我有个比较简便的记忆方法,内外联结的区别是内联结将去除所有不符合条件的记录,而外联结则保留其中部分。外左联结与外右联结的区别在于如果用A左联结B则A中所有记录都会保留在结果中,此时B中只有符合联结条件的记录,而右联结相反,这样也就不会混淆了。
    2014-05-05

最新评论