Skip to content

Commit

Permalink
TiDB auto increment MySQL-compatible behavior clarification (#19861) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-chi-bot authored Mar 4, 2025
1 parent 1a33ec2 commit 45e8209
Showing 1 changed file with 34 additions and 10 deletions.
44 changes: 34 additions & 10 deletions auto-increment.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,25 +389,49 @@ SELECT * FROM t;
## MySQL 兼容模式
从 v6.4.0 开始,TiDB 实现了中心化分配自增 ID 的服务,可以支持 TiDB 实例不缓存数据,而是每次请求都访问中心化服务获取 ID。
TiDB 提供了一种兼容 MySQL 的自增列模式,该模式能确保 ID 严格递增且间隙最小。要启用此模式,需在建表时将 `AUTO_ID_CACHE` 设置为 `1`:
当前中心化分配服务内置在 TiDB 进程,类似于 DDL Owner 的工作模式。有一个 TiDB 实例将充当“主”的角色提供 ID 分配服务,而其它的 TiDB 实例将充当“备”角色。当“主”节点发生故障时,会自动进行“主备切换”,从而保证中心化服务的高可用。
```sql
CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 1;
```
当 `AUTO_ID_CACHE` 设置为 `1` 时,所有 TiDB 实例生成的 ID 严格全局递增,每个 ID 保证全局唯一,相较于默认缓存模式(`AUTO_ID_CACHE 0` 具有 30000 个缓存值),ID 间隙显著缩小。
MySQL 兼容模式的使用方式是,建表时将 `AUTO_ID_CACHE` 设置为 `1`
例如,启用 `AUTO_ID_CACHE 1` 后可以生成如下序列
```sql
CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 1;
INSERT INTO t VALUES (); -- Returns ID 1
INSERT INTO t VALUES (); -- Returns ID 2
INSERT INTO t VALUES (); -- Returns ID 3
-- After failover
INSERT INTO t VALUES (); -- Might return ID 5
```
相比之下,使用默认缓存(`AUTO_ID_CACHE 0`)时可能出现较大间隙:
```sql
INSERT INTO t VALUES (); -- Returns ID 1
INSERT INTO t VALUES (); -- Returns ID 2
-- New TiDB instance allocates next batch
INSERT INTO t VALUES (); -- Returns ID 30001
```
尽管 `AUTO_ID_CACHE 1` 能保证 ID 严格递增且不会出现类似 `AUTO_ID_CACHE 0` 的大幅间隙,但在以下场景中仍可能出现微小间隙。这些间隙是维持 ID 全局唯一性和严格递增特性的必要代价:
- 主实例退出或崩溃的故障恢复期间
使用 MySQL 兼容模式后,能保证 ID **唯一**、**单调递增**,行为几乎跟 MySQL 完全一致。即使跨 TiDB 实例访问,ID 也不会出现回退。只有在中心化分配自增 ID 服务的“主” TiDB 实例进程退出(如该 TiDB 节点重启)或者异常崩溃时,才有可能造成部分 ID 不连续。这是因为主备切换时,“备” 节点需要丢弃一部分之前的“主” 节点已经分配的 ID,以保证 ID 不出现重复。
- TiDB 节点滚动升级期间
- 正常并发事务场景(与 MySQL 类似)
> **注意:**
>
> 在 TiDB 各个版本中,`AUTO_ID_CACHE` 设置为 `1` 都表明 TiDB 不再缓存 ID,但是不同版本的实现方式不一样
> `AUTO_ID_CACHE 1` 的行为和性能在不同 TiDB 版本中的演进如下
>
> - 对于 TiDB v6.4.0 之前的版本,由于每次分配 ID 都需要通过一个 TiKV 事务完成 `AUTO_INCREMENT` 值的持久化修改,因此设置 `AUTO_ID_CACHE` 为 `1` 会出现性能下降。
> - 对于 v6.4.0 及以上版本,由于引入了中心化的分配服务,`AUTO_INCREMENT` 值的修改只是在 TiDB 服务进程中的一个内存操作,相较于之前版本更快。
> - 将 `AUTO_ID_CACHE` 设置为 `0` 表示 TiDB 使用默认的缓存大小 `30000`。
使用 MySQL 兼容模式后,能保证 ID **唯一**、**单调递增**,行为几乎跟 MySQL 完全一致。即使跨 TiDB 实例访问,ID 也不会出现回退。只有在中心化分配自增 ID 服务的“主” TiDB 实例进程退出(如该 TiDB 节点重启)或者异常崩溃时,才有可能造成部分 ID 不连续。这是因为主备切换时,“备” 节点需要丢弃一部分之前的“主” 节点已经分配的 ID,以保证 ID 不出现重复。
> - v6.4.0 之前:每次 ID 分配需通过一个 TiKV 事务完成,会影响性能。
> - v6.4.0 起:引入集中式分配服务,ID 分配转为内存操作,性能显著提升。
> - v8.1.0 起:移除主节点退出时的自动 `forceRebase` 操作以实现快速重启。虽然故障恢复时可能产生额外非连续 ID,但可避免大量表使用 `AUTO_ID_CACHE 1` 时可能出现的写入阻塞。
## 使用限制
Expand Down

0 comments on commit 45e8209

Please sign in to comment.