Temporal values are stored in 时间值作为UTC值存储在TIMESTAMP
columns as UTC values, and values inserted into and retrieved from TIMESTAMP
columns are converted between the session time zone and UTC. TIMESTAMP
列中,插入时间戳列和从时间戳列检索的值在会话时区和UTC之间转换。(This is the same type of conversion performed by the (这与CONVERT_TZ()
function. CONVERT_TZ()
函数执行的转换类型相同。If the session time zone is UTC, there is effectively no time zone conversion.)如果会话时区为UTC,则实际上没有时区转换。)
Due to conventions for local time zone changes such as Daylight Saving Time (DST), conversions between UTC and non-UTC time zones are not one-to-one in both directions. 由于夏令时(DST)等本地时区更改的约定,UTC和非UTC时区之间的转换不是双向的一对一。UTC values that are distinct may not be distinct in another time zone. 不同的UTC值在其他时区中可能不不同。The following example shows distinct UTC values that become identical in a non-UTC time zone:以下示例显示在非UTC时区中变得相同的不同UTC值:
mysql>CREATE TABLE tstable (ts TIMESTAMP);
mysql>SET time_zone = 'UTC'; -- insert UTC values
mysql>INSERT INTO tstable VALUES
('2018-10-28 00:30:00'),
('2018-10-28 01:30:00');
mysql>SELECT ts FROM tstable;
+---------------------+ | ts | +---------------------+ | 2018-10-28 00:30:00 | | 2018-10-28 01:30:00 | +---------------------+ mysql>SET time_zone = 'MET'; -- retrieve non-UTC values
mysql>SELECT ts FROM tstable;
+---------------------+ | ts | +---------------------+ | 2018-10-28 02:30:00 | | 2018-10-28 02:30:00 | +---------------------+
To use named time zones such as 要使用命名时区,如'MET'
or 'Europe/Amsterdam'
, the time zone tables must be properly set up. 'MET'
或'Europe/Amsterdam'
,必须正确设置时区表。For instructions, see Section 5.1.15, “MySQL Server Time Zone Support”.有关说明,请参阅第5.1.15节,“MySQL服务器时区支持”。
You can see that the two distinct UTC values are the same when converted to the 您可以看到,两个不同的UTC值在转换为'MET'
time zone. 'MET'
时区时是相同的。This phenomenon can lead to different results for a given 这种现象可能会导致给定TIMESTAMP
column query, depending on whether the optimizer uses an index to execute the query.TIMESTAMP
列查询的不同结果,这取决于优化器是否使用索引执行查询。
Suppose that a query selects values from the table shown earlier using a 假设查询使用WHERE
clause to search the ts
column for a single specific value such as a user-provided timestamp literal:WHERE
子句从前面显示的表中选择值,以在ts
列中搜索单个特定值,例如用户提供的时间戳文字:
SELECT ts FROM tstable
WHERE ts = 'literal
';
Suppose further that the query executes under these conditions:进一步假设查询在以下条件下执行:
The session time zone is not UTC and has a DST shift. 会话时区不是UTC,具有DST班次。For example:例如:
SET time_zone = 'MET';
Unique UTC values stored in the 由于DST移位,存储在时间戳列中的唯一UTC值在会话时区中不唯一。TIMESTAMP
column are not unique in the session time zone due to DST shifts. (The example shown earlier illustrates how this can occur.)(前面显示的示例说明了如何实现这一点。)
The query specifies a search value that is within the hour of entry into DST in the session time zone.查询指定在会话时区中输入DST的小时内的搜索值。
Under those conditions, the comparison in the 在这些条件下,WHERE
clause occurs in different ways for nonindexed and indexed lookups and leads to different results:WHERE
子句中的比较以不同的方式进行非索引和索引查找,并导致不同的结果:
If there is no index or the optimizer cannot use it, comparisons occur in the session time zone. 如果没有索引或优化器无法使用它,则会在会话时区中进行比较。The optimizer performs a table scan in which it retrieves each 优化器执行表扫描,检索每个ts
column value, converts it from UTC to the session time zone, and compares it to the search value (also interpreted in the session time zone):ts
列值,将其从UTC转换为会话时区,并将其与搜索值(也在会话时区中解释)进行比较:
mysql>SELECT ts FROM tstable
WHERE ts = '2018-10-28 02:30:00';
+---------------------+ | ts | +---------------------+ | 2018-10-28 02:30:00 | | 2018-10-28 02:30:00 | +---------------------+
Because the stored 由于存储的ts
values are converted to the session time zone, it is possible for the query to return two timestamp values that are distinct as UTC values but equal in the session time zone: One value that occurs before the DST shift when clocks are changed, and one value that was occurs after the DST shift.ts
值被转换为会话时区,因此查询可能返回两个时间戳值,这两个时间戳值与UTC值不同,但在会话时区中相等:一个值发生在时钟更改时DST移位之前,另一个值发生在DST移位之后。
If there is a usable index, comparisons occur in UTC. 如果有可用的索引,则以UTC为单位进行比较。The optimizer performs an index scan, first converting the search value from the session time zone to UTC, then comparing the result to the UTC index entries:优化器执行索引扫描,首先将搜索值从会话时区转换为UTC,然后将结果与UTC索引项进行比较:
mysql>ALTER TABLE tstable ADD INDEX (ts);
mysql>SELECT ts FROM tstable
WHERE ts = '2018-10-28 02:30:00';
+---------------------+ | ts | +---------------------+ | 2018-10-28 02:30:00 | +---------------------+
In this case, the (converted) search value is matched only to index entries, and because the index entries for the distinct stored UTC values are also distinct, the search value can match only one of them.在这种情况下,(转换的)搜索值仅与索引项匹配,并且由于存储的不同UTC值的索引项也是不同的,因此搜索值只能与其中一个匹配。
Due to different optimizer operation for nonindexed and indexed lookups, the query produces different results in each case. 由于优化器对非索引和索引查找的操作不同,查询在每种情况下都会产生不同的结果。The result from the nonindexed lookup returns all values that match in the session time zone. 非索引查找的结果返回会话时区中匹配的所有值。The indexed lookup cannot do so:索引查找无法执行此操作:
It is performed within the storage engine, which knows only about UTC values.它在存储引擎中执行,存储引擎只知道UTC值。
For the two distinct session time zone values that map to the same UTC value, the indexed lookup matches only the corresponding UTC index entry and returns only a single row.对于映射到同一UTC值的两个不同会话时区值,索引查找仅匹配相应的UTC索引项,并仅返回一行。
In the preceding discussion, the data set stored in 在前面的讨论中,tstable
happens to consist of distinct UTC values. tstable
中存储的数据集恰好由不同的UTC值组成。In such cases, all index-using queries of the form shown match at most one index entry.在这种情况下,所有使用所示形式的查询的索引最多匹配一个索引项。
If the index is not 如果索引不是UNIQUE
, it is possible for the table (and the index) to store multiple instances of a given UTC value. UNIQUE
,则表(和索引)可以存储给定UTC值的多个实例。For example, the 例如,ts
column might contain multiple instances of the UTC value '2018-10-28 00:30:00'
. ts
列可能包含UTC值'2018-10-28 00:30:00'
的多个实例。In this case, the index-using query would return each of them (converted to the MET value 在这种情况下,使用查询的索引将返回它们中的每一个(转换为结果集中的MET值'2018-10-28 02:30:00'
in the result set). '2018-10-28 02:30:00'
)。It remains true that index-using queries match the converted search value to a single value in the UTC index entries, rather than matching multiple UTC values that convert to the search value in the session time zone.确实,使用查询的索引将转换的搜索值与UTC索引项中的单个值相匹配,而不是与转换为会话时区中搜索值的多个UTC值相匹配。
If it is important to return all 如果返回会话时区中匹配的所有ts
values that match in the session time zone, the workaround is to suppress use of the index with an IGNORE INDEX
hint:ts
值很重要,变通方法是使用IGNORE INDEX
提示来禁止使用索引:
mysql>SELECT ts FROM tstable
IGNORE INDEX (ts)
WHERE ts = '2018-10-28 02:30:00';
+---------------------+ | ts | +---------------------+ | 2018-10-28 02:30:00 | | 2018-10-28 02:30:00 | +---------------------+
The same lack of one-to-one mapping for time zone conversions in both directions occurs in other contexts as well, such as conversions performed with the 在其他上下文中,如使用FROM_UNIXTIME()
and UNIX_TIMESTAMP()
functions. FROM_UNIXTIME()
和UNIX_TIMESTAMP()
函数执行的转换,在两个方向上的时区转换同样缺乏一对一的映射。See Section 12.7, “Date and Time Functions”.请参阅第12.7节,“日期和时间功能”。