Skip to content

Commit bdfc3b3

Browse files
committed
*: Add active-active doc
1 parent fca56d5 commit bdfc3b3

11 files changed

+631
-1
lines changed

TOC.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@
178178
- [日志过滤器](/ticdc/ticdc-filter.md)
179179
- [DDL 同步](/ticdc/ticdc-ddl.md)
180180
- [双向复制](/ticdc/ticdc-bidirectional-replication.md)
181+
- [Active-Active 双向同步](/ticdc/ticdc-active-active-replication.md)
182+
- [Active-Active 表](/active-active-table.md)
183+
- [Soft Delete 表](/soft-delete-table.md)
181184
- 监控告警
182185
- [基本监控指标](/ticdc/ticdc-summary-monitor.md)
183186
- [详细监控指标](/ticdc/monitor-ticdc.md)

active-active-table.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: Active-Active 表
3+
summary: 介绍 Active-Active 表在 TiDB 层面的作用、创建方式、相关系统变量与限制。
4+
---
5+
6+
# Active-Active 表
7+
8+
Active-Active 表是 TiDB 为 Active-Active(双活)同步场景提供的表能力。它通过隐藏列记录写入时间戳,并结合软删除(`SOFTDELETE`)机制,为多集群多写场景下的冲突解决(Last Write Wins,LWW)提供基础能力。
9+
10+
> **说明:**
11+
>
12+
> 本文档仅介绍 Active-Active 表在 TiDB 层如何创建和使用。如何配置 TiCDC 进行双向同步请参阅相关文档。
13+
14+
## 使用前提
15+
16+
- 你需要部署多个 TiDB 集群,并在集群间部署 TiCDC 同步链路(用于跨集群同步变更)。
17+
- 你需要确保各集群的 PD 生成的时间戳在全局范围内可比较且不会冲突。为此,需要为每个集群配置 PD 的 `tso-max-index``tso-unique-index`(详见 [PD 配置文件](/pd-configuration-file.md#tso-max-index)[PD 配置文件](/pd-configuration-file.md#tso-unique-index))。
18+
- 建议为各集群配置 NTP 等时间同步机制,避免因时钟漂移导致事务提交失败或等待时间过长。
19+
20+
> **注意:**
21+
>
22+
> Active-Active 同步不提供跨集群的全局事务一致性,属于最终一致性方案。对于同一行的并发写入可能产生“丢失更新”等现象,请谨慎评估业务适用性。
23+
24+
## 创建 Active-Active 表
25+
26+
Active-Active 表通过表选项 `ACTIVE_ACTIVE='ON'` 启用,并且**必须同时启用软删除**`SOFTDELETE=RETENTION ...`)。`SOFTDELETE` 选项仅支持 `RETENTION ...``'OFF'`,不支持 `'ON'`
27+
28+
### 通过数据库选项统一启用(推荐)
29+
30+
你可以在创建数据库时启用 `ACTIVE_ACTIVE``SOFTDELETE`,该数据库下新创建的表会自动继承这些选项:
31+
32+
```sql
33+
CREATE DATABASE aa_example ACTIVE_ACTIVE='ON' SOFTDELETE=RETENTION 7 DAY;
34+
35+
USE aa_example;
36+
CREATE TABLE message (
37+
id INT PRIMARY KEY,
38+
text VARCHAR(10)
39+
);
40+
```
41+
42+
通过 `SHOW CREATE TABLE` 可以看到这些选项会以注释形式展示(用于 MySQL 兼容),例如:
43+
44+
```sql
45+
SHOW CREATE TABLE message\G
46+
```
47+
48+
示例输出如下(内容会包含 `/*T![active_active] ACTIVE_ACTIVE='ON' */``/*T![softdelete] SOFTDELETE=RETENTION 7 DAY */` 等片段):
49+
50+
```text
51+
*************************** 1. row ***************************
52+
Table: message
53+
Create Table: CREATE TABLE `message` (
54+
`id` int NOT NULL,
55+
`text` varchar(10) DEFAULT NULL,
56+
PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
57+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![active_active] ACTIVE_ACTIVE='ON' */ /*T![softdelete] SOFTDELETE=RETENTION 7 DAY */ /*T![softdelete] SOFTDELETE_JOB_ENABLE='ON' */ /*T![softdelete] SOFTDELETE_JOB_INTERVAL='24h' */
58+
```
59+
60+
### 在建表时单独启用
61+
62+
你也可以在建表时直接指定选项:
63+
64+
```sql
65+
CREATE TABLE message (
66+
id INT PRIMARY KEY,
67+
text VARCHAR(10)
68+
) ACTIVE_ACTIVE='ON' SOFTDELETE=RETENTION 7 DAY;
69+
```
70+
71+
### Soft Delete 相关配置
72+
73+
Active-Active 表同时也是 Soft Delete 表。如何配置 `SOFTDELETE` 的保留期、后台清理任务开关与执行间隔,请参阅 [Soft Delete 表](/soft-delete-table.md#调整-soft-delete-相关选项)
74+
75+
> **注意:**
76+
>
77+
> Active-Active 表不支持将 `SOFTDELETE` 设置为 `'OFF'`,否则会报错。
78+
79+
## 隐藏列与冲突解决(LWW)
80+
81+
启用 Active-Active 后,TiDB 会为表增加一个隐藏列 `_tidb_origin_ts`,用于记录该行数据在上游集群的原始提交时间戳(TiCDC 写入下游时填充)。当 `_tidb_origin_ts``NULL` 时表示该行由本地事务写入;当 `_tidb_origin_ts` 不为 `NULL` 时表示该行由上游变更同步而来。
82+
83+
同时,TiDB 提供一个只读列 `_tidb_commit_ts` 用于查询该行在本地集群的提交时间戳。`_tidb_commit_ts` 不属于真实表结构,不能用于 `ADD COLUMN``ADD INDEX` 等 DDL。
84+
85+
在冲突处理时,可以用如下表达式表示一行数据用于 LWW 冲突解决的时间戳:
86+
87+
```sql
88+
IFNULL(_tidb_origin_ts, _tidb_commit_ts)
89+
```
90+
91+
示例:
92+
93+
```sql
94+
DROP TABLE IF EXISTS message_lww;
95+
CREATE TABLE message_lww (
96+
id INT PRIMARY KEY,
97+
text VARCHAR(10)
98+
) ACTIVE_ACTIVE='ON' SOFTDELETE=RETENTION 7 DAY;
99+
100+
INSERT INTO message_lww VALUES (1, 'local'), (2, 'up');
101+
102+
-- 为了展示效果,这里通过手动写入 _tidb_origin_ts 来模拟 TiCDC 在下游写入时填充该列。正式环境下不建议修改 _tidb_origin_ts 列,否则可能导致 Active-Active 同步结果不一致。
103+
UPDATE message_lww SET _tidb_origin_ts=464677399908313272 WHERE id=2;
104+
105+
SELECT
106+
id,
107+
_tidb_origin_ts,
108+
_tidb_commit_ts,
109+
IFNULL(_tidb_origin_ts, _tidb_commit_ts) AS lww_ts
110+
FROM message_lww
111+
ORDER BY id;
112+
```
113+
114+
```text
115+
+----+--------------------+--------------------+--------------------+
116+
| id | _tidb_origin_ts | _tidb_commit_ts | lww_ts |
117+
+----+--------------------+--------------------+--------------------+
118+
| 1 | <null> | 464677389206814721 | 464677389206814721 |
119+
| 2 | 464677399908313272 | 464677437959045121 | 464677399908313272 |
120+
+----+--------------------+--------------------+--------------------+
121+
```
122+
123+
- `id=1``_tidb_origin_ts``NULL`,表示该行由本地事务写入,此时 `lww_ts` 取值来自 `_tidb_commit_ts`
124+
- `id=2``_tidb_origin_ts` 不为 `NULL`,表示该行由上游变更同步而来,此时 `lww_ts` 取值来自 `_tidb_origin_ts`
125+
126+
### 本地写入覆盖上游写入时的行为
127+
128+
当你在本地集群对一行“来自上游”的数据执行写入(例如 `UPDATE`)时,TiDB 会把这次写入视为本地写入,并将该行的 `_tidb_origin_ts` 重置为 `NULL`。同时,本地事务的提交时间戳会保证大于该行的“LWW 时间戳”(即更新前的 `IFNULL(_tidb_origin_ts, _tidb_commit_ts)`),以避免旧写入覆盖新写入。若本地 PD 分配的 TSO 落后于该行的“LWW 时间戳”,事务提交可能会短暂等待重试;在时钟漂移较大时,事务也可能失败。
129+
130+
示例(继续使用上一节的 `message_lww`):
131+
132+
```sql
133+
SELECT id, text, _tidb_origin_ts FROM message_lww ORDER BY id;
134+
135+
UPDATE message_lww SET text='local2' WHERE id=2;
136+
137+
SELECT id, text, _tidb_origin_ts FROM message_lww ORDER BY id;
138+
```
139+
140+
```text
141+
+----+-------+--------------------+
142+
| id | text | _tidb_origin_ts |
143+
+----+-------+--------------------+
144+
| 1 | local | NULL |
145+
| 2 | up | 464677399908313272 |
146+
+----+-------+--------------------+
147+
+----+--------+-----------------+
148+
| id | text | _tidb_origin_ts |
149+
+----+--------+-----------------+
150+
| 1 | local | NULL |
151+
| 2 | local2 | NULL |
152+
+----+--------+-----------------+
153+
```
154+
155+
> **注意:**
156+
>
157+
> 不建议业务显式修改 `_tidb_origin_ts`,否则可能导致 Active-Active 同步结果不一致。
158+
159+
## Soft Delete(必需)
160+
161+
Active-Active 表必须同时启用 Soft Delete。Soft Delete 表的语义(DML 改写、`RECOVER VALUES` 数据恢复、后台清理任务等)请参阅 [Soft Delete 表](/soft-delete-table.md)
162+
163+
> **注意:**
164+
>
165+
> 不要在 `tidb_translate_softdelete_sql=OFF` 的情况下对启用 `SOFTDELETE` 的表执行 `DELETE` 操作,否则可能会造成 Active-Active 同步的不一致。更多信息请参阅 [Soft Delete 表](/soft-delete-table.md#软删除语义与数据恢复)
166+
167+
## 监控与排查
168+
169+
- 只读 SESSION 变量 [`tidb_cdc_active_active_sync_stats`](/system-variables.md#tidb_cdc_active_active_sync_stats) 仅供 TiCDC 读取,用于获取 Active-Active 同步的冲突跳过统计信息。
170+
- Soft Delete 表的统计信息(`INFORMATION_SCHEMA.TIDB_SOFTDELETE_TABLE_STATS`)详见 [Soft Delete 表](/soft-delete-table.md#监控与排查)
171+
172+
## 使用限制
173+
174+
- Active-Active 表必须同时启用 `SOFTDELETE`
175+
- Active-Active 表必须显式指定主键。
176+
- Active-Active 表(Soft Delete 表)当前不支持 `UNIQUE` 索引(包括 `ADD UNIQUE INDEX``CREATE UNIQUE INDEX`)。
177+
- Active-Active 表不支持外键(`FOREIGN KEY`)。
178+
- Active-Active 表不支持临时表(`TEMPORARY TABLE` / `GLOBAL TEMPORARY TABLE`)。
179+
- 目前不支持通过 `ALTER TABLE` 修改表的 `ACTIVE_ACTIVE` 启用状态。
180+
- 不支持通过 DDL 删除、重命名或修改 `_tidb_origin_ts``_tidb_softdelete_time` 等内部隐藏列。
181+
- Active-Active 表同时适用 Soft Delete 表的其他限制,详见 [Soft Delete 表](/soft-delete-table.md#使用限制)

keywords.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ TiDB 从 v7.5.3 和 v7.6.0 开始提供 [`INFORMATION_SCHEMA.KEYWORDS`](/informa
6161

6262
- ACCOUNT
6363
- ACTION
64+
- ACTIVE_ACTIVE
6465
- ADD (R)
6566
- ADMIN
6667
- ADVISE
@@ -573,6 +574,7 @@ TiDB 从 v7.5.3 和 v7.6.0 开始提供 [`INFORMATION_SCHEMA.KEYWORDS`](/informa
573574
- RESTORES
574575
- RESTRICT (R)
575576
- RESUME
577+
- RETENTION
576578
- REUSE
577579
- REVERSE
578580
- REVOKE (R)
@@ -626,6 +628,9 @@ TiDB 从 v7.5.3 和 v7.6.0 开始提供 [`INFORMATION_SCHEMA.KEYWORDS`](/informa
626628
- SLOW
627629
- SMALLINT (R)
628630
- SNAPSHOT
631+
- SOFTDELETE
632+
- SOFTDELETE_JOB_ENABLE
633+
- SOFTDELETE_JOB_INTERVAL
629634
- SOME
630635
- SOURCE
631636
- SPATIAL (R)

pd-configuration-file.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,20 @@ PD 配置文件比命令行参数支持更多的选项。你可以在 [conf/conf
120120
+ 默认值:50ms
121121
+ 最小值:1ms
122122

123+
### `tso-max-index`
124+
125+
+ 用于在多 PD 集群场景下生成全局唯一的 TSO。`tso-max-index`[`tso-unique-index`](#tso-unique-index) 共同决定 TSO 逻辑部分的分配方式,从而避免不同集群产生的 TSO 冲突。
126+
+ 默认值:0
127+
+`tso-max-index` 设置为非 0 值时,需要为每个 PD 集群设置不同的 `tso-unique-index`,并确保 `tso-unique-index` 的取值不超过 `tso-max-index`
128+
+ 该配置常用于 Active-Active 场景下跨集群比较时间戳,更多信息请参考 [Active-Active 表](/active-active-table.md)
129+
130+
### `tso-unique-index`
131+
132+
+ 用于在多 PD 集群场景下标识当前 PD 集群的唯一索引。不同集群必须配置不同值,以避免生成的 TSO 冲突。
133+
+ 默认值:0
134+
+ 通常需要与 [`tso-max-index`](#tso-max-index) 配合使用。例如,若有 N 个集群,建议将 `tso-max-index` 设置为 N,并将各集群的 `tso-unique-index` 设置为 1..N(每个集群不同)。
135+
+ 该配置常用于 Active-Active 场景下跨集群比较时间戳,更多信息请参考 [Active-Active 表](/active-active-table.md)
136+
123137
## pd-server
124138

125139
pd-server 相关配置项。

0 commit comments

Comments
 (0)