diff --git a/configure-time-zone.md b/configure-time-zone.md index bc431d07bd5b..58bc97ffd2e3 100644 --- a/configure-time-zone.md +++ b/configure-time-zone.md @@ -1,55 +1,65 @@ --- title: 时区支持 -summary: TiDB 使用的时区由全局变量和 session 变量决定。全局变量的默认值是 System,实际时区在集群初始化时设置。可以通过设置全局时区和 session 变量来修改时区。Timestamp 数据类型受时区影响,而 Datetime/Date/Time 不受影响。在导数据时需注意主从库的时区设定是否一致。 +summary: TiDB 的时区设置由 `time_zone` 系统变量控制,可以在会话级别或全局级别进行设置。`TIMESTAMP` 数据类型的的显示值受时区设置影响,但 `DATETIME`、`DATE` 或 `TIME` 数据类型不受影响。在数据迁移时,需要特别注意主库和从库的时区设置是否一致。 --- # 时区支持 -TiDB 使用的时区由 `time_zone` 全局变量和 session 变量决定。`time_zone` 的默认值是 `System`,`System` 对应的实际时区在 `TiDB` 集群 bootstrap 初始化时设置。具体逻辑如下: +TiDB 使用的时区由 [`time_zone`](/system-variables.md#time_zone) 系统变量决定,该变量可以在会话级别或全局级别设置。`time_zone` 的默认值为 `SYSTEM`。`SYSTEM` 对应的实际时区是在 TiDB 集群 bootstrap 初始化时配置的,具体逻辑如下: -* 优先使用 `TZ` 环境变量 -* 如果失败,则从 `/etc/localtime` 的实际软链地址提取。 -* 如果上面两种都失败则使用 `UTC` 作为系统时区。 +1. TiDB 优先使用 `TZ` 环境变量。 +2. 如果 `TZ` 环境变量不可用,TiDB 会从 `/etc/localtime` 的软链接中读取时区信息。 +3. 如果上述方法均失败,TiDB 将使用 `UTC` 作为系统时区。 -在运行过程中可以修改全局时区: +## 查看时区 -{{< copyable "sql" >}} +要查看当前全局时区、客户端时区或系统时区的值,可以执行以下语句: ```sql -SET GLOBAL time_zone = timezone; +SELECT @@global.time_zone, @@session.time_zone, @@global.system_time_zone; ``` -TiDB 还可以通过设置 session 变量 `time_zone` 为每个连接维护各自的时区。默认条件下,这个值取的是全局变量 `time_zone` 的值。修改 session 使用的时区: +## 设置时区 -{{< copyable "sql" >}} +在 TiDB 中,`time_zone` 系统变量的值可以设置为以下格式之一: -```sql -SET time_zone = timezone; -``` +- `SYSTEM`(默认值),表示使用系统时间。 +- 相对于 UTC 时间的偏移,比如 `'+10:00'` 或 `'-6:00'`。 +- 某个时区的名字,比如 `'Europe/Helsinki'`、`'US/Eastern'` 或 `'MET'`。 -使用以下 SQL 语句查看当前全局时区、客户端时区和系统时区的值: +根据需要,你可以在全局级别或会话级别设置 TiDB 的时区: -{{< copyable "sql" >}} +- 设置全局时区: -```sql -SELECT @@global.time_zone, @@session.time_zone, @@global.system_time_zone; -``` + ```sql + SET GLOBAL time_zone = ${time-zone-value}; + ``` + + 例如,执行以下语句可以将全局时区设置为 UTC: + + ```sql + SET GLOBAL time_zone = 'UTC'; + ``` -设置 `time_zone` 的值的格式: +- 设置会话的时区: -* 'SYSTEM' 表明使用系统时间 -* 相对于 UTC 时间的偏移,比如 '+10:00' 或者 '-6:00' -* 某个时区的名字,比如 'Europe/Helsinki','US/Eastern' 或 'MET' + ```sql + SET time_zone = ${time-zone-value}; + ``` -`NOW()` 和 `CURTIME()` 的返回值都受到时区设置的影响。 + 例如,执行以下语句可以将当前会话的时区设置为 US/Pacific: -> **注意:** -> -> 只有 Timestamp 数据类型的值是受时区影响的。可以理解为,Timestamp 数据类型的实际表示使用的是(字面值 + 时区信息)。其它时间和日期类型,比如 Datetime/Date/Time 是不包含时区信息的,所以也不受到时区变化的影响。 + ```sql + SET time_zone = 'US/Pacific'; + ``` -{{< copyable "sql" >}} +## 受时区设置影响的函数和数据类型 -{{< copyable "sql" >}} +对于时区敏感的时间值,例如由 [`NOW()`](/functions-and-operators/date-and-time-functions.md) 和 `CURTIME()` 函数返回的值,它们的显示和处理会受到当前会话时区设置的影响。如需进行时区转换,可以使用 `CONVERT_TZ()` 函数。若要获取基于 UTC 的时间戳以避免时区相关问题,可以使用 `UTC_TIMESTAMP()` 函数。 + +在 TiDB 中,`TIMESTAMP` 数据类型会记录时间戳的具体数值和时区信息,因此它的显示值会受到时区设置的影响。其他数据类型(如 `DATETIME`、`DATE` 和 `TIME`)不记录时区信息,因此它们的值不会受到时区变化的影响。 + +例如: ```sql create table t (ts timestamp, dt datetime); @@ -59,8 +69,6 @@ create table t (ts timestamp, dt datetime); Query OK, 0 rows affected (0.02 sec) ``` -{{< copyable "sql" >}} - ```sql set @@time_zone = 'UTC'; ``` @@ -69,8 +77,6 @@ set @@time_zone = 'UTC'; Query OK, 0 rows affected (0.00 sec) ``` -{{< copyable "sql" >}} - ```sql insert into t values ('2017-09-30 11:11:11', '2017-09-30 11:11:11'); ``` @@ -79,8 +85,6 @@ insert into t values ('2017-09-30 11:11:11', '2017-09-30 11:11:11'); Query OK, 1 row affected (0.00 sec) ``` -{{< copyable "sql" >}} - ```sql set @@time_zone = '+8:00'; ``` @@ -89,8 +93,6 @@ set @@time_zone = '+8:00'; Query OK, 0 rows affected (0.00 sec) ``` -{{< copyable "sql" >}} - ```sql select * from t; ``` @@ -104,8 +106,17 @@ select * from t; 1 row in set (0.00 sec) ``` -上面的例子中,无论怎么调整时区的值,Datetime 类型字段的值是不受影响的,而 Timestamp 则随着时区改变,显示的值会发生变化。其实 Timestamp 持久化到存储的值始终没有变化过,只是根据时区的不同显示值不同。 +在以上示例中,无论如何调整时区值,`DATETIME` 数据类型的值不会受到影响。然而,`TIMESTAMP` 数据类型的显示值会根据时区的变化而变化。事实上,存储在数据库中的 `TIMESTAMP` 值始终没有变化过,只是根据时区的不同显示的值不同。 + +## 时区设置的注意事项 + +- 在 `TIMESTAMP` 和 `DATETIME` 值的转换过程中,会涉及到时区。这种情况一律基于当前会话的 `time_zone` 时区处理。 +- 数据迁移时,需要特别注意主库和从库的时区设置是否一致。 +- 为了获取准确的时间戳,强烈建议使用网络时间协议 (NTP) 或精确时间协议 (PTP) 服务配置可靠的时钟。有关如何检查 NTP 服务的信息,请参考[检测及安装 NTP 服务](/check-before-deployment.md#检测及安装-ntp-服务)。 +- 当使用遵循夏令时 (Daylight Saving Time, DST) 的时区时,请注意可能出现时间戳不明确或不存在的情况,特别是在对这些时间戳进行计算时。 +- MySQL 需要使用 [`mysql_tzinfo_to_sql`](https://dev.mysql.com/doc/refman/8.4/en/mysql-tzinfo-to-sql.html) 将操作系统的时区数据库转换为 `mysql` 数据库中的表。TiDB 则可以利用 Go 编程语言的内置时区处理能力,直接从操作系统的时区数据库中读取时区数据文件。 -Timestamp 类型和 Datetime 等类型的值,两者相互转换的过程中,会涉及到时区。这种情况一律基于 session 的当前 `time_zone` 时区处理。 +## 另请参阅 -另外,用户在导数据的过程中,也要需注意主库和从库之间的时区设定是否一致。 +- [日期和时间类型](/data-type-date-and-time.md) +- [日期和时间函数](/functions-and-operators/date-and-time-functions.md) \ No newline at end of file