Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update timezone docs #19204

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 49 additions & 38 deletions configure-time-zone.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,61 @@ summary: TiDB 使用的时区由全局变量和 session 变量决定。全局变

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

英文的 summary 不如中文详细,可以和中文保持一致。

# 时区支持

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` 作为系统时区。
- TiDB 优先使用 `TZ` 环境变量
- 如果 `TZ` 环境变量不可用,TiDB 会从 `/etc/localtime` 的软链接中读取时区信息
- 如果上述方法均失败,TiDB 将使用 `UTC` 作为系统时区。
Comment on lines +11 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- TiDB 优先使用 `TZ` 环境变量。
- 如果 `TZ` 环境变量不可用,TiDB 会从 `/etc/localtime` 的软链接中读取时区信息。
- 如果上述方法均失败,TiDB 将使用 `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`) 不记录时区信息,因此它们的值不会受到时区变化的影响。
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
在 TiDB 中,`TIMESTAMP` 数据类型会记录时间戳的具体数值和时区信息,因此它的显示值会受到时区设置的影响。其他数据类型(如 `DATETIME``DATE``TIME` 不记录时区信息,因此它们的值不会受到时区变化的影响。
在 TiDB 中,`TIMESTAMP` 数据类型会记录时间戳的具体数值和时区信息,因此它的显示值会受到时区设置的影响。其他数据类型(如 `DATETIME``DATE``TIME`)不记录时区信息,因此它们的值不会受到时区变化的影响。


例如:

```sql
create table t (ts timestamp, dt datetime);
Expand All @@ -60,8 +70,6 @@ create table t (ts timestamp, dt datetime);
Query OK, 0 rows affected (0.02 sec)
```

{{< copyable "sql" >}}

```sql
set @@time_zone = 'UTC';
```
Expand All @@ -70,8 +78,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');
```
Expand All @@ -80,8 +86,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';
```
Expand All @@ -90,8 +94,6 @@ set @@time_zone = '+8:00';
Query OK, 0 rows affected (0.00 sec)
```

{{< copyable "sql" >}}

```sql
select * from t;
```
Expand All @@ -105,8 +107,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-服务)。
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- 为了获取准确的时间戳,强烈建议使用网络时间协议NTP或精确时间协议PTP服务配置可靠的时钟。有关如何检查 NTP 服务的信息,请参考[检测及安装 NTP 服务](/check-before-deployment.md#检测及安装-ntp-服务)
- 为了获取准确的时间戳,强烈建议使用网络时间协议 (NTP) 或精确时间协议 (PTP) 服务配置可靠的时钟。有关如何检查 NTP 服务的信息,请参考[检测及安装 NTP 服务](/check-before-deployment.md#检测及安装-ntp-服务)

- 当使用遵循夏令时 (Daylight Saving Time, DST) 的时区时,请注意可能出现时间戳不明确或不存在的情况,特别是在对这些时间戳进行计算时。
- MySQL 需要使用 `mysql_tzinfo_to_sql` 将操作系统的时区数据库转换为 `mysql` 数据库中的表。TiDB 则可以利用 Go 编程语言的内置时区处理能力,直接从操作系统的时区数据库中读取时区数据文件。
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- MySQL 需要使用 `mysql_tzinfo_to_sql` 将操作系统的时区数据库转换为 `mysql` 数据库中的表。TiDB 则可以利用 Go 编程语言的内置时区处理能力,直接从操作系统的时区数据库中读取时区数据文件。
- 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)
Loading