-
Notifications
You must be signed in to change notification settings - Fork 1.2k
add document about stale read transaction #6347
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
Changes from all commits
00fb603
1b6e53f
dc84157
cc0e35c
14e2cf3
0145732
808a889
c8f276d
d84d1a3
f3fba9e
03f3ccd
72ec40a
bdb6ca9
b53e3ad
790d75a
e897d19
911de89
85bc899
d6c070c
293c4f4
27f0caf
0a79a09
6cee97b
19c44aa
36a7487
83a7454
218a107
23584df
ebc77c1
18cb715
c260ad8
7f0b302
1f5b6ac
bf2d730
baddd7c
efc245a
f352558
9158919
21c7f85
559162e
4fd6e55
b842a92
c504dd9
75605f7
e769eca
de996cb
d76fc54
b6f57fb
8e3f8ef
8bfcc03
7655d8e
7d57426
b7e6c94
2d9a830
556f007
757242b
e8405e7
8a103c0
84ddbea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,259 @@ | ||
| --- | ||
| title: 使用 AS OF TIMESTAMP 语法读取历史数据 | ||
| summary: 了解如何使用 AS OF TIMESTAMP 语法读取历史数据。 | ||
| --- | ||
|
|
||
| # 使用 AS OF TIMESTAMP 语法读取历史数据 | ||
|
|
||
| 本文档介绍如何通过 `AS OF TIMESTAMP` 语句使用 [Stale Read](/stale-read.md) 功能来读取 TiDB 历史版本数据,包括具体的操作示例以及历史数据的保存策略。 | ||
|
|
||
| TiDB 支持通过标准 SQL 接口,即通过 `AS OF TIMESTAMP` SQL 语法的形式读取历史数据,无需特殊的服务器或者驱动器。当数据被更新或删除后,你可以通过 SQL 接口将更新或删除前的数据读取出来。 | ||
|
|
||
| > **注意:** | ||
| > | ||
| > 读取历史数据时,即使当前数据的表结构相较于历史数据的表结构已经发生改变,历史数据也会以当时的历史表结构来返回。 | ||
|
|
||
| ## 语法方式 | ||
|
|
||
| 你可以通过以下三种方式使用 `AS OF TIMESTAMP` 语法: | ||
|
|
||
| - [`SELECT ... FROM ... AS OF TIMESTAMP`](/sql-statements/sql-statement-select.md) | ||
| - [`START TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-start-transaction.md) | ||
| - [`SET TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-set-transaction.md) | ||
|
Comment on lines
+21
to
+22
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这两个链接可以链接到本文中的对应章节吗?如果需要给出对应的 transaction 语法,是否可以在后面对应的章节里再提供呢?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 两边都已经进行了链接。 |
||
|
|
||
| 如果你想要指定一个精确的时间点,可在 `AS OF TIMESTAMP` 中使用日期时间和时间函数,日期时间的格式为:"2016-10-08 16:45:26.999",最小时间精度范围为毫秒,通常可只写到秒,例如 "2016-10-08 16:45:26"。你也可以通过 `NOW(3)` 函数获得精确到毫秒的当前时间。 | ||
|
|
||
| 如果你想要指定一个时间范围,需要使用 `TIDB_BOUNDED_STALENESS()` 函数。使用该函数,TiDB 会在指定的时间范围内选择一个合适的时间戳,该时间戳能保证所访问的副本上不存在开始于这个时间戳之前且还没有提交的相关事务,即能保证所访问的可用副本上执行读取操作而且不会被阻塞。用法为 `TIDB_BOUNDED_STALENESS(t1, t2)`,其中 `t1` 和 `t2` 为时间范围的两端,支持使用日期时间和时间函数,示例如下: | ||
|
|
||
| - `AS OF TIMESTAMP '2016-10-08 16:45:26'` 表示读取在 2016 年 10 月 8 日 16 点 45 分 26 秒时最新的数据。 | ||
| - `AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND` 表示读取 10 秒前最新的数据。 | ||
| - `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29')` 表示读取在 2016 年 10 月 8 日 16 点 45 分 26 秒到 29 秒的时间范围内尽可能新的数据。 | ||
| - `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() - INTERVAL 20 SECOND, NOW())` 表示读取 20 秒前到现在的时间范围内尽可能新的数据。 | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 加一个说明我们推荐的是 5 秒左右的历史读吧(最佳实践)。 cc @NingLin-P 5 秒 ok 吧?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 最好多测测几个场景再确定 |
||
| 注意: 除了指定时间戳,`AS OF TIMESTAMP` 语法最常用使用的方式是读几秒前的数据。如果采用这种方式,取值范围推荐为读 5 秒以上的历史数据。 | ||
|
|
||
| ## 示例 | ||
|
|
||
|
nolouch marked this conversation as resolved.
|
||
| 本节通过多个示例介绍 `AS OF TIMESTAMP` 语法的不同使用方法。在本节中,先介绍如何准备用于恢复的数据,再分别展示如何通过 `SELECT`、`START TRANSACTION READ ONLY AS OF TIMESTAMP`、`SET TRANSACTION READ ONLY AS OF TIMESTAMP` 以及 `SELECT` 子句使用 `AS OF TIMESTAMP`。 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| ### 准备数据 | ||
|
|
||
| 在准备数据阶段,创建一张表,并插入若干行数据: | ||
|
|
||
| ```sql | ||
| create table t (c int); | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.01 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| insert into t values (1), (2), (3); | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 3 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| 查看表中的数据: | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 2 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| 查看当前时间: | ||
|
|
||
| ```sql | ||
| select now(); | ||
| ``` | ||
|
|
||
| ``` | ||
| +---------------------+ | ||
| | now() | | ||
| +---------------------+ | ||
| | 2021-05-26 16:45:26 | | ||
| +---------------------+ | ||
| 1 row in set (0.00 sec) | ||
| ``` | ||
|
|
||
| 更新某一行数据: | ||
|
|
||
| ```sql | ||
| update t set c=22 where c=2; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 1 row affected (0.00 sec) | ||
| ``` | ||
|
|
||
| 确认数据已经被更新: | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 22 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| ### 通过 `SELECT` 读取历史数据 | ||
|
|
||
| 通过 [`SELECT ... FROM ... AS OF TIMESTAMP`](/sql-statements/sql-statement-select.md) 语句读取一个基于历史时间的数据。 | ||
|
|
||
| ```sql | ||
| select * from t as of timestamp '2021-05-26 16:45:26'; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 2 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| > **注意:** | ||
| > | ||
| > 通过 `SELECT` 语句读取多个表时要保证 TIMESTAMP EXPRESSION 是一致的。 比如: `select * from t as of timestamp NOW() - INTERVAL 2 SECOND, c as of timestamp NOW() - INTERVAL 2 SECOND;`。此外,在 `SELECT` 语句中,你必须要指定相关数据表的 as of 信息,若不指定,`SELECT` 语句会默认读最新的数据。 | ||
|
|
||
| ### 通过 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 读取历史数据 | ||
|
|
||
| 通过 [`START TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-start-transaction.md) 语句,你可以开启一个基于历史时间的只读事务,该事务基于所提供的历史时间来读取历史数据。 | ||
|
|
||
| ```sql | ||
| start transaction read only as of timestamp '2021-05-26 16:45:26'; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 2 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| commit; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| 当事务结束后,即可读取最新数据。 | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 22 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| > **注意:** | ||
| > | ||
| > 通过 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 开启的事务为只读事务。假如在该事务中执行写入操作,操作将会被该事务拒绝。 | ||
|
|
||
| ### 通过 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 读取历史数据 | ||
|
|
||
| 通过 [`SET TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-set-transaction.md) 语句,你可以将下一个事务设置为基于指定历史时间的只读事务。该事务将会基于所提供的历史时间来读取历史数据。 | ||
|
|
||
| ```sql | ||
| set transaction read only as of timestamp '2021-05-26 16:45:26'; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| begin; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 2 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| ```sql | ||
| commit; | ||
| ``` | ||
|
|
||
| ``` | ||
| Query OK, 0 rows affected (0.00 sec) | ||
| ``` | ||
|
|
||
| 当事务结束后,即可读取最新数据。 | ||
|
|
||
| ```sql | ||
| select * from t; | ||
| ``` | ||
|
|
||
| ``` | ||
| +------+ | ||
| | c | | ||
| +------+ | ||
| | 1 | | ||
| | 22 | | ||
| | 3 | | ||
| +------+ | ||
| 3 rows in set (0.00 sec) | ||
| ``` | ||
|
|
||
| > **注意:** | ||
| > | ||
| > 通过 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 开启的事务为只读事务。假如在该事务中执行写入操作,操作将会被该事务拒绝。 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| title: 在三数据中心下就近读取数据 | ||
| summary: 了解通过 Stale Read 功能在三数据中心下就近读取数据,减少跨数据中心请求。 | ||
| --- | ||
|
|
||
| # 在三数据中心下就近读取数据 | ||
|
|
||
| 在三数据中心模式下,Region 的三个副本都会隔离在各个数据中心里。然而在强一致读的要求下,tidb 的每一个查询都需要访问对应数据的 Leader 副本,而查询的来源可能和 Leader 所在的数据中心不一致,这就会引起跨数据中心的数据访问,从而造成访问的延迟上升。本文主要介绍使用 [Stale Read](/stale-read.md) 功能,以牺牲数据实时性的方式,避免跨数据中心的访问,从而降低访问的延迟。 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tidb -> TiDB |
||
|
|
||
| ## 部署三数据中心的 TiDB 集群 | ||
|
|
||
| 部署三数据中心的方法,参考[同城多数据中心部署 TiDB](/multi-data-centers-in-one-city-deployment.md)。 | ||
|
|
||
| 请注意,如果 TiKV 和 TiDB 都有 `labels` 配置项,在给 TiKV 和 TiDB 配置标签时,同一个数据中心下的 TiKV 和 TiDB 应该配置相同的 `zone` 标签。假设 TiKV 和 TiDB 都在 `dc-1` 数据中心下,那么两者都需要配置如下标签: | ||
|
|
||
| ``` | ||
| [labels] | ||
| zone=dc-1 | ||
| ``` | ||
|
|
||
| ## 使用 Stale Read 就近读取数据 | ||
|
|
||
|
Yisaer marked this conversation as resolved.
|
||
| [Stale Read](/stale-read.md) 为用户提供了一种读取历史数据的一种机制。使用 Stale Read 功能,你能从指定时间点或时间范围内读取对应的历史数据,从而避免数据同步带来延迟。在部分跨数据中心部署的场景中使用 Stale Read 功能,通过牺牲一定的实时性,TiDB 可就近访问对应数据所在当前中心的副本,避免跨数据中心的网络延迟,降低整体查询的访问延迟。 | ||
|
|
||
| 当 TiDB 收到 Stale Read 查询时,假如对应的 TiDB 配置了 `zone` 标签,就会将请求发送到对应数据副本所在 TiKV 拥有相同的 `zone` 标签的节点上。 | ||
|
|
||
| 如何使用 Stale Read 查询,参考[使用 AS OF TIMESTAMP 语法读取历史数据](/as-of-timestamp.md)。 | ||
Uh oh!
There was an error while loading. Please reload this page.