10bet网址
MySQL 8.0参考手册
相关的文档10bet官方网站 本手册下载 本手册节选

5.1.15 MySQL服务器时区支持

本节介绍MySQL维护的时区设置、如何加载命名时间支持所需的系统表、如何保持最新的时区更改以及如何启用闰秒支持。

从MySQL 8.0.19开始,对插入的datetime值也支持时区偏移;看到第11.2.2节“DATE, DATETIME和TIMESTAMP类型”,以查询更多资料。

有关复制设置中的时区设置的信息,请参见第17.5.1.14节“复制和系统功能”而且第17.5.1.33节“复制和时区”

时区变量

MySQL服务器维护几个时区设置:

  • 系统时区。当服务器启动时,它尝试自动确定主机的时区,并使用它来设置system_time_zone系统变量。此后该值不会改变。

    若要显式指定MySQL Server启动时的系统时区,请设置TZ环境变量mysqld.如果使用。启动服务器mysqld_safe,它的——时区Option提供了另一种设置系统时区的方法。的容许值TZ而且——时区是系统的依赖。参考您的操作系统文档,查看哪些值是可接受的。10bet官方网站

  • 服务器当前时区。全球time_zone系统变量表示服务器当前运行的时区。最初的time_zone值是“系统”,表示服务器的时区与系统的时区一致。

    请注意

    如果设置为系统,每个需要进行时区计算的MySQL函数调用都会调用系统库来确定当前的系统时区。此调用可能受到全局互斥锁的保护,从而导致争用。

    方法显式指定初始全局服务器时区值——时区选项,或者您可以在选项文件中使用以下行:

    时区= '时区

    如果你有SYSTEM_VARIABLES_ADMIN特权(或已弃用的超级特权),您可以在运行时通过以下语句设置全局服务器时区值:

    SET GLOBAL time_zone =时区
  • 每会话时区。连接的每个客户机都有自己的会话时区设置,由会话给出time_zone变量。最初,会话变量从全局变量获取其值time_zone变量,但客户端可以通过以下语句更改自己的时区:

    设置time_zone =时区

会话时区设置会影响时区敏感的时间值的显示和存储。这包括函数显示的值,例如现在()CURTIME (),以及存储在其中并从中检索的值时间戳列。值时间戳列从会话时区转换为UTC用于存储,从UTC转换为会话时区用于检索。

设置会话时区不影响功能显示的值UTC_TIMESTAMP ()或值日期时间,或DATETIME列。这些数据类型中的值也不存储在UTC中;只有从。转换时,时区才适用时间戳值。如果你想要特定于语言环境的算术日期时间,或DATETIME值,将它们转换为UTC,执行算术,然后转换回来。

当前的全局和会话时区值可以像这样检索:

选择@@GLOBAL。time_zone,@@SESSION.time_zone;

时区值可以用几种格式给出,但都不区分大小写:

  • 的价值“系统”,表示服务器的时区与系统的时区一致。

  • 作为指示窗体UTC偏移量的字符串HH毫米,以a为前缀+-,如' + 10点'“6”,或' + 05:30 '.前导零可选地用于小时值小于10;在这种情况下,MySQL在存储和检索值时将前导0前置。MySQL转换“0”“0:00”“+ 00:00”

    在MySQL 8.0.19之前,这个值必须在这个范围内“59”“+ 13”、包容;从MySQL 8.0.19开始,允许的范围是“13:59””+“夏令时间、包容。

  • 作为已命名的时区,例如欧洲/赫尔辛基的“我们/东”“见过”,或UTC的

    请注意

    中的时区信息表不能使用命名时区mysql数据库已经创建并填充。否则,使用已命名的时区会导致错误:

    SET time_zone = 'UTC';错误1298 (HY000):未知或不正确的时区:'UTC'

填充时区表

的几个表mysql存在用于存储时区信息的系统模式(参见第5.3节“mysql系统架构”).MySQL安装过程创建时区表,但不加载它们。要手动完成此操作,请使用以下说明。

请注意

加载时区信息不一定是一次性操作,因为信息偶尔会更改。当发生这样的更改时,使用旧规则的应用程序就会过时,您可能会发现有必要重新加载时区表,以保持MySQL服务器使用的信息是最新的。看到跟上时区的变化

如果你的系统有自己的zoneinfo数据库(描述时区的文件集),使用mysql_tzinfo_to_sql程序加载时区表。这类系统的例子有Linux、macOS、FreeBSD和Solaris。这些文件的一个可能位置是/usr/share/zoneinfo目录中。如果您的系统没有zoneinfo数据库,您可以使用一个可下载的包,如本节后面所述。

要从命令行加载时区表,将zoneinfo目录路径名传递给mysql_tzinfo_to_sql并将输出发送到mysql程序。例如:

Mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

mysql这里显示的命令假设您使用一个帐户连接到服务器,例如控件中修改表的特权mysql系统模式。请根据实际情况调整连接参数。

mysql_tzinfo_to_sql读取系统的时区文件并从中生成SQL语句。mysql处理这些语句以加载时区表。

mysql_tzinfo_to_sql也可用于加载单个时区文件或生成闰秒信息:

  • 加载一个时区文件tz_file对应于一个时区名称tz_name,调用mysql_tzinfo_to_sql是这样的:

    mysql_tzinfo_to_sqltz_filetz_name| mysql -u root -p mysql

    使用这种方法,您必须执行一个单独的命令,为服务器需要了解的每个已命名的区域加载时区文件。

  • 如果您的时区必须考虑闰秒,请像这样初始化闰秒信息,其中tz_file是您的时区文件的名称:

    mysql_tzinfo_to_sql——飞跃tz_file| mysql -u root -p mysql

在运行mysql_tzinfo_to_sql,重新启动服务器,使其不再继续使用以前缓存的任何时区数据。

如果您的系统没有zoneinfo数据库(例如,Windows),您可以使用一个包含SQL语句的包,该包可以从MySQL Developer Zone下载:

https://dev.10bet靠谱mys10bet手机中文版ql.com/downloads/timezones.html
警告

如果您的系统有一个zoneinfo数据库,请使用可下载的时区包。使用mysql_tzinfo_to_sql实用程序。否则,您可能会导致MySQL和您系统上的其他应用程序在日期时间处理方面的差异。

要使用已下载的sql语句时区包,请将其解压,然后将解压后的文件内容加载到时区表中:

Mysql -u root -p Mysql <file_name

然后重新启动服务器。

警告

使用可下载的时区包,其中包含MyISAM表。这适用于较老的MySQL版本。MySQL现在使用InnoDB对于时区表。试图用MyISAM表原因的问题。

跟上时区的变化

当时区规则发生变化时,使用旧规则的应用程序将过时。要保持最新,必须确保您的系统使用了当前的时区信息。对于MySQL来说,有很多因素需要考虑:

  • 如果MySQL服务器的时区设置为,则操作系统时间会影响MySQL服务器的次数值系统.确保您的操作系统正在使用最新的时区信息。对于大多数操作系统,最新的更新或服务包会使您的系统做好时间更改的准备。查看您的操作系统供应商的网站,以获得针对时间更改的更新。

  • 如果你更换系统的/etc/localtime时区文件,其版本使用的规则与有效的规则不同mysqld启动、重启mysqld所以它使用了更新的规则。否则,mysqld可能不会注意到系统改变了时间。

  • 如果在MySQL中使用命名时区,请确保mysql数据库是最新的:

    • 如果您的系统有自己的zoneinfo数据库,请在zoneinfo数据库更新时重新加载MySQL时区表。

    • 对于没有自己的zoneinfo数据库的系统,请检查MySQL Developer Zone以获取更新。当有新的更新可用时,下载它并使用它替换当前时区表的内容。

    有关这两种方法的说明,请参见填充时区表mysqld缓存它查找到的时区信息,因此在更新时区表之后,重新启动mysqld以确保它不会继续提供过时的时区数据。

如果您不确定指定的时区是否可用,以便用于服务器的时区设置或用于设置自己的时区的客户端,请检查您的时区表是否为空。以下查询确定包含时区名称的表是否有行:

SELECT COUNT(*) FROM mysql.time_zone_name;+----------+ | 数 (*) | +----------+ | 0  | +----------+

计数为零表示表为空。在这种情况下,目前没有应用程序使用命名时区,您不需要更新表(除非您希望启用命名时区支持)。计数大于零表示表不是空的,它的内容可用于命名时区支持。在这种情况下,一定要重新加载时区表,以便使用指定时区的应用程序能够获得正确的查询结果。

要检查您的MySQL安装是否因日光节约时间规则的更改而正确更新,请使用如下测试。该示例使用的值适用于2007年3月11日凌晨2点发生在美国的夏令时1小时变化。

测试使用以下查询:

SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') AS time1, CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') AS time2;

这两个时间值表示DST更改发生的时间,使用命名时区需要使用时区表。期望的结果是两个查询返回相同的结果(输入时间,转换为'US/Central'时区的等价值)。

在更新时区表之前,你会看到如下错误的结果:

+---------------------+---------------------+ | time1 | time2  | +---------------------+---------------------+ | 2007-03-11 01:00:00 | 2007-03-11 02:00:00  | +---------------------+---------------------+

在更新表之后,你应该会看到正确的结果:

+---------------------+---------------------+ | time1 | time2  | +---------------------+---------------------+ | 2007-03-11 01:00:00 | 2007-03-11 01:00:00  | +---------------------+---------------------+

时区闰秒支持

闰秒值返回的时间部分以: 59:59.这意味着函数如现在()可以在闰秒期间连续两秒或三秒返回相同的值。文字时态值的时间部分以: 59:60: 59:61被认为是无效的。

如果有必要搜索时间戳闰秒前一秒的值,如果使用与的比较,可能会得到异常的结果YYYY-MM-DD hh: mm: ss值。下面的示例演示了这一点。它将会话时区更改为UTC,因此内部时区之间没有差异时间戳值(UTC)和显示值(应用了时区校正)。

mysql> CREATE TABLE t1 (a INT, ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ts);查询OK, 0 rows affected (0.01 sec) mysql>——change to UTC mysql> SET time_zone = '+00:00';查询OK, 0 rows affected (0.00 sec) mysql>——模拟现在()= '2008-12-31 23:59:59' mysql> SET timestamp = 1230767999;查询OK, 0行影响(0.00 sec) mysql> INSERT INTO t1 (a) VALUES (1);查询OK, 1 row affected (0.00 sec) mysql>——模拟现在()= '2008-12-31 23:59:60' mysql> SET时间戳= 1230768000;查询OK, 0行影响(0.00 sec) mysql> INSERT INTO t1 (a) VALUES (2);SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;+------+---------------------+--------------------+ | 一个| ts | UNIX_TIMESTAMP (ts ) | +------+---------------------+--------------------+ | 1 | 2008-12-31 23:59:59 | 1230767999 | | 2 | 2008-12-31 23:59:59 | 1230768000  | +------+---------------------+--------------------+ 2行(0.00秒)mysql >——只有non-leap值匹配mysql > SELECT * FROM t1, ts = 2008-12-31 23:59:59的;+------+---------------------+ | 一个| ts  | +------+---------------------+ | 1 | 2008-12-31 23:59:59  | +------+---------------------+ 1行组(0.00秒)mysql >——跳跃值60秒=无效mysql > SELECT * FROM t1, ts = ' 2008-12-31 23:59:60 ';空集,2个警告(0.00秒)

为了解决这个问题,你可以使用一个基于实际存储在列中的UTC值的比较,它应用了闰秒校正:

SELECT * FROM t1 WHERE UNIX_TIMESTAMP(ts) = 1230768000;+------+---------------------+ | 一个| ts  | +------+---------------------+ | 2 | 2008-12-31 23:59:59  | +------+---------------------+ 1行集(0.00秒)