This section describes the time zone settings maintained by MySQL, how to load the system tables required for named time support, how to stay current with time zone changes, and how to enable leap-second support.本节介绍MySQL维护的时区设置,如何加载命名时间支持所需的系统表,如何及时了解时区更改,以及如何启用闰秒支持。
Beginning with MySQL 8.0.19, time zone offsets are also supported for inserted datetime values; see Section 11.2.2, “The DATE, DATETIME, and TIMESTAMP Types”, for more information.从MySQL 8.0.19开始,插入的日期时间值也支持时区偏移;有关更多信息,请参阅第11.2.2节,“日期、日期时间和时间戳类型”。
For information about time zone settings in replication setups, see Section 17.5.1.14, “Replication and System Functions” and Section 17.5.1.33, “Replication and Time Zones”.有关复制设置中时区设置的信息,请参阅第17.5.1.14节,“复制和系统功能”和第17.5.1.33节,“复制与时区”。
MySQL Server maintains several time zone settings:MySQL服务器维护多个时区设置:
The system time zone. When the server starts, it attempts to determine the time zone of the host machine automatically and uses it to set the 系统时区。当服务器启动时,它会尝试自动确定主机的时区,并使用它来设置system_time_zone
system variable.system_time_zone
系统变量。
To explicitly specify the system time zone for MySQL Server at startup, set the 要在启动时明确指定MySQL Server的系统时区,请在启动mysqld之前设置TZ
environment variable before you start mysqld. TZ
环境变量。If you start the server using mysqld_safe, its 如果使用mysqld_safe启动服务器,其--timezone
option provides another way to set the system time zone. --timezone
选项提供了另一种设置系统时区的方法。The permissible values for TZ
and --timezone
are system dependent. TZ
和--timezone
的允许值取决于系统。Consult your operating system documentation to see what values are acceptable.请查阅操作系统文档,了解哪些值是可接受的。
The server current time zone. The global 服务器当前时区。全局time_zone
system variable indicates the time zone the server currently is operating in. time_zone
系统变量表示服务器当前运行的时区。The initial 初始time_zone
value is 'SYSTEM'
, which indicates that the server time zone is the same as the system time zone.time_zone
值为'SYSTEM'
,表示服务器时区与系统时区相同。
If set to 如果设置为SYSTEM
, every MySQL function call that requires a time zone calculation makes a system library call to determine the current system time zone. This call may be protected by a global mutex, resulting in contention.SYSTEM
,则每个需要时区计算的MySQL函数调用都会调用系统库来确定当前的系统时区。此调用可能受到全局互斥体的保护,从而导致争用。
The initial global server time zone value can be specified explicitly at startup with the 可以在启动时使用命令行上的--default-time-zone
option on the command line, or you can use the following line in an option file:--default-timezone
选项显式指定初始全局服务器时区值,也可以在选项文件中使用以下行:
default-time-zone='timezone
'
If you have the 如果您拥有SYSTEM_VARIABLES_ADMIN
privilege (or the deprecated SUPER
privilege), you can set the global server time zone value at runtime with this statement:SYSTEM_VARIABLES_ADMIN
权限(或已弃用的SUPER
权限),则可以在运行时使用以下语句设置全局服务器时区值:
SET GLOBAL time_zone = timezone
;
Per-session time zones. Each client that connects has its own session time zone setting, given by the session 每个会话时区。每个连接的客户端都有自己的会话时区设置,由会话time_zone
variable. time_zone
变量给出。Initially, the session variable takes its value from the global 最初,会话变量从全局time_zone
variable, but the client can change its own time zone with this statement:time_zone
变量中获取值,但客户端可以使用以下语句更改自己的时区:
SET time_zone = timezone
;
The session time zone setting affects display and storage of time values that are zone-sensitive. 会话时区设置会影响对区域敏感的时间值的显示和存储。This includes the values displayed by functions such as 这包括NOW()
or CURTIME()
, and values stored in and retrieved from TIMESTAMP
columns. NOW()
或CURTIME()
等函数显示的值,以及存储在TIMESTAMP
列中和从中检索的值。Values for TIMESTAMP
columns are converted from the session time zone to UTC for storage, and from UTC to the session time zone for retrieval.TIMESTAMP
列的值从会话时区转换为UTC进行存储,从UTC转换为会话时区进行检索。
The session time zone setting does not affect values displayed by functions such as 会话时区设置不会影响UTC_TIMESTAMP()
or values in DATE
, TIME
, or DATETIME
columns. UTC_TIMESTAMP()
等函数显示的值或DATE
、time
或DATETIME
列中的值。Nor are values in those data types stored in UTC; the time zone applies for them only when converting from 这些数据类型中的值也不以UTC存储;时区仅在从TIMESTAMP
values. TIMESTAMP
值转换时适用于它们。If you want locale-specific arithmetic for 如果您希望对DATE
, TIME
, or DATETIME
values, convert them to UTC, perform the arithmetic, and then convert back.DATE
、TIME
或DATETIME
值进行特定于区域设置的算术运算,请将其转换为UTC,执行算术运算,然后再转换回来。
The current global and session time zone values can be retrieved like this:当前的全局和会话时区值可以按如下方式检索:
SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;
timezone
values can be given in several formats, none of which are case-sensitive:值可以以多种格式给出,但都不区分大小写:
As the value 作为值'SYSTEM'
, indicating that the server time zone is the same as the system time zone.'SYSTEM'
,表示服务器时区与系统时区相同。
As a string indicating an offset from UTC of the form 表示UTC偏移量的字符串,格式为[
, prefixed with a H
]H
:MM
+
or -
, such as '+10:00'
, '-6:00'
, or '+05:30'
. [H]H:MM
,前缀为+
或-
,如'+10:00'
、'-6:00'
或'+05:30'
。A leading zero can optionally be used for hours values less than 10; MySQL prepends a leading zero when storing and retriving the value in such cases. 前导零可用于小于10的小时值;在这种情况下,MySQL在存储和检索值时会预置一个前导零。MySQL converts MySQL将'-00:00'
or '-0:00'
to '+00:00'
.'-00:00'
或'-0:00'
转换为'+00:00'
。
Prior to MySQL 8.0.19, this value had to be in the range 在MySQL 8.0.19之前,此值必须在'-12:59'
to '+13:00'
, inclusive; beginning with MySQL 8.0.19, the permitted range is '-13:59'
to '+14:00'
, inclusive.'-12:59'
到'+13:00'
的范围内,包括首尾两个值;从MySQL 8.0.19开始,允许的范围为'-13:59'
到'+14:00'
,包括首尾两个值。
As a named time zone, such as 作为命名时区,如'Europe/Helsinki'
, 'US/Eastern'
, 'MET'
, or 'UTC'
.'Europe/Helsinki'
、'US/Eastern'
、'MET'
或'UTC'
。
Named time zones can be used only if the time zone information tables in the 仅当mysql
database have been created and populated. Otherwise, use of a named time zone results in an error:mysql
数据库中的时区信息表已创建并填充时,才能使用命名时区。否则,使用命名时区会导致错误:
mysql> SET time_zone = 'UTC';
ERROR 1298 (HY000): Unknown or incorrect time zone: 'UTC'
Several tables in the mysql
system schema exist to store time zone information (see Section 5.3, “The mysql System Schema”). mysql
系统模式中存在几个表来存储时区信息(见第5.3节,“mysql系统架构”)。The MySQL installation procedure creates the time zone tables, but does not load them. To do so manually, use the following instructions.MySQL安装过程会创建时区表,但不会加载它们。要手动执行此操作,请使用以下说明。
Loading the time zone information is not necessarily a one-time operation because the information changes occasionally. 加载时区信息不一定是一次性操作,因为信息偶尔会发生变化。When such changes occur, applications that use the old rules become out of date and you may find it necessary to reload the time zone tables to keep the information used by your MySQL server current. 当发生此类更改时,使用旧规则的应用程序会过时,您可能会发现有必要重新加载时区表,以保持MySQL服务器使用的信息是最新的。See Staying Current with Time Zone Changes.请参阅跟上时区变化。
If your system has its own zoneinfo database (the set of files describing time zones), use the mysql_tzinfo_to_sql program to load the time zone tables. 如果您的系统有自己的zoneinfo
数据库(描述时区的文件集),请使用mysql_tzinfo_to_sql程序加载时区表。Examples of such systems are Linux, macOS, FreeBSD, and Solaris. 此类系统的示例包括Linux、macOS、FreeBSD和Solaris。One likely location for these files is the 这些文件的一个可能位置是/usr/share/zoneinfo
directory. /usr/share/zoneinfo
目录。If your system has no zoneinfo database, you can use a downloadable package, as described later in this section.如果您的系统没有zoneinfo数据库,您可以使用可下载的软件包,如本节稍后所述。
To load the time zone tables from the command line, pass the zoneinfo directory path name to mysql_tzinfo_to_sql and send the output into the mysql program. 要从命令行加载时区表,请将zoneinfo目录路径名传递给mysql_tzinfo_To_sql,并将输出发送到mysql程序中。For example:例如:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
The mysql command shown here assumes that you connect to the server using an account such as 这里显示的mysql命令假设您使用root
that has privileges for modifying tables in the mysql
system schema. Adjust the connection parameters as required.root
等帐户连接到服务器,该帐户具有修改mysql
系统模式中表的权限。根据需要调整连接参数。
mysql_tzinfo_to_sql reads your system's time zone files and generates SQL statements from them. mysql_tzinfo_to_sql读取系统的时区文件并从中生成sql语句。mysql processes those statements to load the time zone tables.mysql处理这些语句以加载时区表。
mysql_tzinfo_to_sql also can be used to load a single time zone file or generate leap second information:mysql_tzinfo_to_sql还可以用于加载单个时区文件或生成闰秒信息:
To load a single time zone file 要加载与时区名称tz_file
that corresponds to a time zone name tz_name
, invoke mysql_tzinfo_to_sql like this:tz_name
对应的单个时区文件tz_file
,请按如下方式调用mysql_tzinfo_To_sql:
mysql_tzinfo_to_sqltz_file
tz_name
| mysql -u root -p mysql
With this approach, you must execute a separate command to load the time zone file for each named zone that the server needs to know about.使用这种方法,您必须执行一个单独的命令,为服务器需要知道的每个命名区域加载时区文件。
If your time zone must account for leap seconds, initialize leap second information like this, where 如果您的时区必须考虑闰秒,请按如下方式初始化闰秒信息,其中tz_file
is the name of your time zone file:tz_file
是您的时区文件的名称:
mysql_tzinfo_to_sql --leap tz_file
| mysql -u root -p mysql
After running mysql_tzinfo_to_sql, restart the server so that it does not continue to use any previously cached time zone data.运行mysql_tzinfo_to_sql后,重新启动服务器,使其不再继续使用任何以前缓存的时区数据。
If your system has no zoneinfo database (for example, Windows), you can use a package containing SQL statements that is available for download at the MySQL Developer Zone:如果您的系统没有zoneinfo数据库(例如Windows),您可以使用MySQL开发者专区提供的包含SQL语句的包进行下载:
https://dev.mysql.com/downloads/timezones.html
Do not use a downloadable time zone package if your system has a zoneinfo database. 如果您的系统有zoneinfo数据库,请不要使用可下载的时区包。Use the mysql_tzinfo_to_sql utility instead. 请改用mysql_tzinfo_to_sql实用程序。Otherwise, you may cause a difference in datetime handling between MySQL and other applications on your system.否则,您可能会导致MySQL和系统上其他应用程序之间的日期时间处理存在差异。
To use an SQL-statement time zone package that you have downloaded, unpack it, then load the unpacked file contents into the time zone tables:要使用已下载的SQL语句时区包,请解压缩它,然后将解压缩的文件内容加载到时区表中:
mysql -u root -p mysql < file_name
Then restart the server.
Do not use a downloadable time zone package that contains 不要使用包含MyISAM
tables. MyISAM
表的可下载时区包。That is intended for older MySQL versions. MySQL now uses 这适用于较旧的MySQL版本。MySQL现在使用InnoDB
for the time zone tables. InnoDB
作为时区表。Trying to replace them with 试图用MyISAM
tables causes problems.MyISAM
表替换它们会导致问题。
When time zone rules change, applications that use the old rules become out of date. To stay current, it is necessary to make sure that your system uses current time zone information is used. For MySQL, there are multiple factors to consider in staying current:当时区规则更改时,使用旧规则的应用程序将过时。为了保持最新状态,有必要确保您的系统使用当前的时区信息。对于MySQL,保持最新状态需要考虑多个因素:
The operating system time affects the value that the MySQL server uses for times if its time zone is set to 如果MySQL服务器的时区设置为SYSTEM
. SYSTEM
,则操作系统时间会影响MySQL服务器使用的时间值。Make sure that your operating system is using the latest time zone information. For most operating systems, the latest update or service pack prepares your system for the time changes. 确保您的操作系统使用的是最新的时区信息。对于大多数操作系统,最新的更新或service pack会使您的系统为时间变化做好准备。Check the website for your operating system vendor for an update that addresses the time changes.请查看您的操作系统供应商的网站,以获取解决时间更改的更新。
If you replace the system's 如果将系统的/etc/localtime
time zone file with a version that uses rules differing from those in effect at mysqld startup, restart mysqld so that it uses the updated rules. /etc/localtime
时区文件替换为使用与mysqld启动时不同的规则的版本,请重新启动mysqld,使其使用更新的规则。Otherwise, mysqld might not notice when the system changes its time.否则,mysqld可能不会注意到系统何时更改时间。
If you use named time zones with MySQL, make sure that the time zone tables in the 如果你在MySQL中使用命名时区,请确保MySQL数据库中的时区表是最新的:mysql
database are up to date:
If your system has its own zoneinfo database, reload the MySQL time zone tables whenever the zoneinfo database is updated.如果您的系统有自己的zoneinfo数据库,请在zoneinfo数据更新时重新加载MySQL时区表。
For systems that do not have their own zoneinfo database, check the MySQL Developer Zone for updates. When a new update is available, download it and use it to replace the content of your current time zone tables.对于没有自己的zoneinfo数据库的系统,请查看MySQL开发人员专区以获取更新。当有新的更新可用时,下载并使用它来替换当前时区表的内容。
For instructions for both methods, see Populating the Time Zone Tables. 有关这两种方法的说明,请参阅填充时区表。mysqld caches time zone information that it looks up, so after updating the time zone tables, restart mysqld to make sure that it does not continue to serve outdated time zone data.mysqld缓存它查找的时区信息,因此在更新时区表后,重新启动mysqld以确保它不会继续提供过时的时区数据。
If you are uncertain whether named time zones are available, for use either as the server's time zone setting or by clients that set their own time zone, check whether your time zone tables are empty. The following query determines whether the table that contains time zone names has any rows:如果您不确定命名的时区是否可用,无论是作为服务器的时区设置还是由设置自己时区的客户端使用,请检查您的时区表是否为空。以下查询确定包含时区名称的表是否有任何行:
mysql> SELECT COUNT(*) FROM mysql.time_zone_name;
+----------+
| COUNT(*) |
+----------+
| 0 |
+----------+
A count of zero indicates that the table is empty. In this case, no applications currently are using named time zones, and you need not update the tables (unless you want to enable named time zone support). 计数为零表示表为空。在这种情况下,当前没有应用程序使用命名时区,您不需要更新表(除非您想启用命名时区支持)。A count greater than zero indicates that the table is not empty and that its contents are available to be used for named time zone support. 计数大于零表示表不为空,其内容可用于命名时区支持。In this case, be sure to reload your time zone tables so that applications that use named time zones can obtain correct query results.在这种情况下,请务必重新加载时区表,以便使用命名时区的应用程序可以获得正确的查询结果。
To check whether your MySQL installation is updated properly for a change in Daylight Saving Time rules, use a test like the one following. The example uses values that are appropriate for the 2007 DST 1-hour change that occurs in the United States on March 11 at 2 a.m.要检查MySQL安装是否针对夏令时规则的更改进行了正确更新,请使用以下测试。该示例使用适用于2007年3月11日凌晨2点美国夏令时1小时变化的值。
The test uses this query:测试使用此查询:
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;
The two time values indicate the times at which the DST change occurs, and the use of named time zones requires that the time zone tables be used. The desired result is that both queries return the same result (the input time, converted to the equivalent value in the 'US/Central' time zone).这两个时间值表示夏令时变化发生的时间,使用命名时区需要使用时区表。期望的结果是两个查询返回相同的结果(输入时间,转换为“美国/中部”时区的等效值)。
Before updating the time zone tables, you see an incorrect result like this:在更新时区表之前,您会看到这样的错误结果:
+---------------------+---------------------+ | time1 | time2 | +---------------------+---------------------+ | 2007-03-11 01:00:00 | 2007-03-11 02:00:00 | +---------------------+---------------------+
After updating the tables, you should see the correct result:更新表格后,您应该看到正确的结果:
+---------------------+---------------------+ | time1 | time2 | +---------------------+---------------------+ | 2007-03-11 01:00:00 | 2007-03-11 01:00:00 | +---------------------+---------------------+
Leap second values are returned with a time part that ends with 闰秒值返回的时间部分以:59:59
. :59:59
结尾。This means that a function such as 这意味着NOW()
can return the same value for two or three consecutive seconds during the leap second. NOW()
等函数可以在闰秒期间连续两到三秒返回相同的值。It remains true that literal temporal values having a time part that ends with 确实,时间部分以:59:60
or :59:61
are considered invalid.:59:60
或:59:61
结尾的文字时间值被视为无效。
If it is necessary to search for 如果需要在闰秒前一秒搜索TIMESTAMP
values one second before the leap second, anomalous results may be obtained if you use a comparison with '
values. YYYY-MM-DD hh:mm:ss
'TIMESTAMP
值,如果将其与'YYYY-MM-DD hh:MM:ss'
值进行比较,可能会获得异常结果。The following example demonstrates this. It changes the session time zone to UTC so there is no difference between internal 以下示例演示了这一点。它将会话时区更改为UTC,因此内部TIMESTAMP
values (which are in UTC) and displayed values (which have time zone correction applied).TIMESTAMP
值(以UTC为单位)和显示值(应用了时区校正)之间没有差异。
mysql>CREATE TABLE t1 (
a INT,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ts)
);
Query OK, 0 rows affected (0.01 sec) mysql>-- change to UTC
mysql>SET time_zone = '+00:00';
Query OK, 0 rows affected (0.00 sec) mysql>-- Simulate NOW() = '2008-12-31 23:59:59'
mysql>SET timestamp = 1230767999;
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t1 (a) VALUES (1);
Query OK, 1 row affected (0.00 sec) mysql>-- Simulate NOW() = '2008-12-31 23:59:60'
mysql>SET timestamp = 1230768000;
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t1 (a) VALUES (2);
Query OK, 1 row affected (0.00 sec) mysql>-- values differ internally but display the same
mysql>SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;
+------+---------------------+--------------------+ | a | ts | UNIX_TIMESTAMP(ts) | +------+---------------------+--------------------+ | 1 | 2008-12-31 23:59:59 | 1230767999 | | 2 | 2008-12-31 23:59:59 | 1230768000 | +------+---------------------+--------------------+ 2 rows in set (0.00 sec) mysql>-- only the non-leap value matches
mysql>SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:59';
+------+---------------------+ | a | ts | +------+---------------------+ | 1 | 2008-12-31 23:59:59 | +------+---------------------+ 1 row in set (0.00 sec) mysql>-- the leap value with seconds=60 is invalid
mysql>SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:60';
Empty set, 2 warnings (0.00 sec)
To work around this, you can use a comparison based on the UTC value actually stored in the column, which has the leap second correction applied:为了解决这个问题,您可以使用基于实际存储在列中的UTC值的比较,该值应用了闰秒校正:
mysql>-- selecting using UNIX_TIMESTAMP value return leap value
mysql>SELECT * FROM t1 WHERE UNIX_TIMESTAMP(ts) = 1230768000;
+------+---------------------+ | a | ts | +------+---------------------+ | 2 | 2008-12-31 23:59:59 | +------+---------------------+ 1 row in set (0.00 sec)