diff --git a/auto-increment.md b/auto-increment.md index da9875b8047b..badb36d70f5e 100644 --- a/auto-increment.md +++ b/auto-increment.md @@ -286,9 +286,8 @@ TiDB 自增 ID 的缓存大小在早期版本中是对用户透明的。从 v3.1 CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 100; Query OK, 0 rows affected (0.02 sec) -INSERT INTO t VALUES(); +INSERT INTO t1 VALUES(); Query OK, 1 row affected (0.00 sec) -Records: 1 Duplicates: 0 Warnings: 0 SELECT * FROM t; +---+ @@ -297,33 +296,94 @@ SELECT * FROM t; | 1 | +---+ 1 row in set (0.01 sec) + +SHOW CREATE TABLE t; ++-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| t | CREATE TABLE `t` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=101 /*T![auto_id_cache] AUTO_ID_CACHE=100 */ | ++-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 row in set (0.00 sec) ``` -此时如果将该列的自增缓存无效化,重新进行隐式分配: +此时如果重启了 TiDB,缓存会丢失,重新进行隐式分配: ```sql -DELETE FROM t; -Query OK, 1 row affected (0.01 sec) - -RENAME TABLE t to t1; -Query OK, 0 rows affected (0.01 sec) - -INSERT INTO t1 VALUES() +INSERT INTO t VALUES(); Query OK, 1 row affected (0.00 sec) -SELECT * FROM t; +select * from t; +-----+ | a | +-----+ +| 1 | | 101 | +-----+ -1 row in set (0.00 sec) +2 rows in set (0.01 sec) ``` 可以看到再一次分配的值为 `101`,说明该表的自增 ID 分配缓存的大小为 `100`。 此外如果在批量插入的 `INSERT` 语句中所需连续 ID 长度超过 `AUTO_ID_CACHE` 的长度时,TiDB 会适当调大缓存以便能够保证该语句的正常插入。 +### 清除自增 ID 缓存 + +一些场景下可能需要清除缓存,例如在某个 TiDB 节点已经分配了缓存的情况下,执行了自增 ID 列的显式写入并且最大值超出了缓存范围。此时如果切回到隐式分配,TiDB 可能会报主键冲突的错误。常见的场景包括: + +- 使用 DM 进行增量同步,下游 TiDB 的写入流量回切到业务时,自增列 ID 的写入模式通常由显式写入转换成隐式分配。 +- 业务混用了显式写入和隐式分配,需要修复潜在的主键冲突错误。 + +你可以执行 `ALTER TABLE` 语句设置 `AUTO_INCREMENT = 0` 来清除集群中所有 TiDB 节点的自增 ID 缓存。例如: + +```sql +CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 100; +Query OK, 0 rows affected (0.02 sec) + +INSERT INTO t VALUES(); +Query OK, 1 row affected (0.02 sec) + +INSERT INTO t VALUES(50); +Query OK, 1 row affected (0.00 sec) + +SELECT * FROM t; ++----+ +| a | ++----+ +| 1 | +| 50 | ++----+ +2 rows in set (0.01 sec) +``` + +```sql +ALTER TABLE t AUTO_INCREMENT = 0; +Query OK, 0 rows affected, 1 warning (0.07 sec) + +SHOW WARNINGS; ++---------+------+-------------------------------------------------------------------------+ +| Level | Code | Message | ++---------+------+-------------------------------------------------------------------------+ +| Warning | 1105 | Can't reset AUTO_INCREMENT to 0 without FORCE option, using 101 instead | ++---------+------+-------------------------------------------------------------------------+ +1 row in set (0.01 sec) + +INSERT INTO t VALUES(); +Query OK, 1 row affected (0.02 sec) + +SELECT * FROM t; ++-----+ +| a | ++-----+ +| 1 | +| 50 | +| 101 | ++-----+ +3 rows in set (0.01 sec) +``` + ### 自增步长和偏移量设置 从 v3.0.9 和 v4.0.rc-1 开始,和 MySQL 的行为类似,自增列隐式分配的值遵循 session 变量 `@@auto_increment_increment` 和 `@@auto_increment_offset` 的控制,其中自增列隐式分配的值 (ID) 将满足式子 `(ID - auto_increment_offset) % auto_increment_increment == 0`。