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

TiDb表主键 id AUTO_INCREMENT=1654033,从mysql迁移到TiDb后现在插入数据自动分配的id小于1654033会报 Duplicate entry ‘1573741’ for key ‘PRIMARY’,确定1573741这个id没有值,请问是什么问题,另外如果不建议使用AUTO_INCREMENT,是否可以使用 AUTO_RANDOM(官网不建议生产使用),如果要把表主键key的AUTO_INCREMENT修改AUTO_RANDOM,应该怎么操作。
当前版本是4.0.9,插入数据会轮流插入当前number之前或之后,感觉应该分region了。

1.上面提示 Duplicate entry for key ‘PRIMARY’ ,能否提供下具体的操作记录;
2.使用 auto_increment 主要是容易引起热点问题,可以考虑打开 alter-primary-key ,然后在建表语句上加上 SHARD_ROW_ID_BITSPRE_SPLIT_REGIONS 来避免热点问题;
3.无法直接在表上将 AUTO_INCREMENT 修改为 AUTO_RANDOM,只能重新建表后再灌入数据。

人为向自增列写入值后 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 个赞

1.正常的插入数据后报Duplicate entry for key ‘PRIMARY’,后端应该自动分了多个region,插入后一段大于当前最大分配至没有问题,后续切换到另外小于当前分配最大值后报错;
2. 请问怎么打开打开 alter-primary-key

执行正常的插入报 Duplicate entry,发现实际分配的id在表中确实不存在,之前同事后台手工执行过insert,之前插入的记录应该跟现在新插入记录将分配的id不一样。

1.麻烦提供一下具体的操作过程,方便我们这边排查和复现;
2.打开 alter-primary-key 参考下:https://docs.pingcap.com/zh/tidb/stable/tidb-configuration-file#alter-primary-key

从mysql迁移到TiDb,同事手工后台向表插入一些数据(未指定id)后,前端业务保存业务数据后就报Duplicate entry

麻烦核实下前端业务保存业务数据时有无指定 id 值,若指定了值,则报错可能是上面 3 楼说的原因;若没有指定值,烦请告知下具体集群版本和复现的操作步骤或截图。

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。