AUTO_INCREMENT引起的Duplicate entry 'xx' for key 'PRIMARY'问题

人为向自增列写入值后 TiDB 分配自增值时报 “Duplicate entry” 错误的处理方法

在集群中有多个 tidb-server 时,人为向自增列写入值之后,可能会导致 TiDB 分配自增值冲突而报 “Duplicate entry” 错误:

假设有这样一个带有自增 ID 的表:create table t(id int unique key auto_increment, c int);

TiDB 实现自增 ID 的原理是每个 tidb-server 实例缓存一段 ID 值用于分配(目前会缓存 30000 个 ID),用完这段值再去取下一段。

假设集群中有两个 tidb-server 实例 A 和 B(A 缓存 [1,30000] 的自增 ID,B 缓存 [30001,60000] 的自增 ID),依次执行如下操作:

客户端向 B 插入一条将 id 设置为 1 的语句 insert into t values (1, 1),并执行成功。

客户端向 A 发送 Insert 语句 insert into t © (1),这条语句中没有指定 id 的值,所以会由 A 分配,当前 A 缓存了 [1, 30000] 这段 ID,所以会分配 1 为自增 ID 的值,并把本地计数器加 1。而此时数据库中已经存在 id 为 1 的数据,最终返回 Duplicated Entry 错误。

处理该问题只需要调大表上的 AUTO_INCREMENT 属性值即可让所有 tidb-server 重新获取一段自增 ID:

  1. 确认表上自增值的最大值:show create table t;

修改表上的自增值最大值到一个更大的值:alter table t AUTO_INCREMENT=120000;

1 个赞