生产出现failed to read auto_random value from storage engine

【 TiDB 使用环境】生产环境
【 TiDB 版本】 v6.5.3
【复现路径】做过哪些操作出现的问题
生产环境一张表出现failed to read auto_random value from storage engine 。表用的是auto_random(5),目前表里id的最大值快到bigint值允许的上限了。
【遇到的问题:问题现象及影响】
表已经插入不了值了。
【资源配置】

看了官方文档对auto_random的解释,还是不太明白分片位数量S的含义,是说每次按5位数的值来分配id吗。现在表插入不了数据了,我设置R的值为54,以后还会不会遇到这个问题?
https://docs.pingcap.com/zh/tidb/stable/auto-random

这位大佬总结的很好。你可以看看。

看了下 提到 官方文档说描述到插入数据时,不建议自行显式指定含有 AUTO_RANDOM 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。

楼主的数据库有手工插入数据了吧,不知道用完了随机数怎么处理

AUTO_RANDOM(S, R)
一般情况下S+R=64,也可以显式指定,例如AUTO_RANDOM(5, 54)
S是分片位,如果分片数量为2的S次方,例如设置5,就是2的5次方也就是32片,会基本平均分配到你的tikv节点上,例如tikv节点为4,那样每个节点就会保存8个分片,可以使所有tikv节点压力均衡。
R是长度位,加上分片位也就是你该字段的长度,例如你前面S设置为5,R默认就是59,那你这个字段的位数就是64(但是你显式设置AUTO_RANDOM(5, 54),这个字段长度就是59),这个值保持单调递增但不保证连续,理论上一个59位的数字,你用一辈子也用不完,但是有例外情况,就是你显式插入了一个数字,例如你在这个字段插入了99999999999999999999999999999999,59位的最大数字,那你下一个自动分配的数字必须比这个字段大,这时就会报错,所以AUTO_RANDOM字段的值不建议显式插入。

00001 00001…
10000 00001…
auto_random(5) 前面5位二进制能组成的不同值数量就是分片数

那我现在遇到这个问题,确实可能是因为之前显式插入了id值,我怎么找到这个id值进行修改呢。现在设置了可用长度R为54,也就意味着自增位为54-1-5=48,我怎么找到这个长度的自增位目前的最大值?

show create table 表名,看一下AUTO_RANDOM_BASE这个值,这个值只能往大了改,不能往小了改。。。

目前表里才十来万数据,就已经插入不了了,是不是在实现机制方面有点不合理? 而且,如果要保证用户绝对地不会显式插入id,似乎也有点难。是否可以把这东西改得更灵活些?

可以选择自行生成 id 数据,这样更符合你的场景,不过会有热点问题。鱼与熊掌不可兼得,等遇到瓶颈再说了

这个是你自己插入了值 你新建一个表 导入过去

只有几万数据,一个显式Insert把数据库搞得业务做不了了,这数据库健壮性有点差了吧?不应该是数据库层面自动处理吗?

如果真的显式插入数据了怎么办,不能不做业务了吧?

看从哪个角度来看待问题:自由也是有规矩的。比如主键要求唯一非空,但我就想在主键上插入2个相同值,数据库凭啥不允许插入呢

修改 allow_auto_random_explicit_insert这个参数为0即可禁止显式插入id

当前id字段的值在别的表里有使用,不能让它自生成。

现在问题是已经有显式插入过的值了,但不知道是哪条?关掉这个也无济于事啊,现在看报错已经是引擎分配不了id值了。

这个有什么命令能单独改吗?

从数据库逻辑来说,不行,你想一想,tidb的autorandom怎么保证random的值每次不重复呢?不可能每次去表里查一下吧?他就是个简单的分片加上递增列构成的,你现在直接显示指定了一个值插进去了,他为了保证后续的值不跟你现在的值重复,只能使得对应自增列比你显式插入的列大。他不会允许你再改小的,不然后面random出来的值不就又可能重复了吗?

1 个赞

麻烦问一下这块相关源码在哪里?怎么算出我当前表还有多少id可用?

你对应报错的表执行下SHOW CREATE TABLE tt;
AUTO_RANDOM_BASE就是他当前的最大值了