Tidb id暴增问题

【 TiDB 使用环境】生产 、测试环境

【 TiDB 版本】v5.1.0

【遇到的问题】
运维同事将测试数据写入到生产,导致生产id无规则变化,后面程序插入的数据id也随着自动增加,导致导出数据开始和结尾id很难定夺(每次导出数据量太大会把库导挂,以前都是10~20亿作为一个任务),TiDB中能否实现将生产表id重新从1递增进行排序。

时间 id变化情况
2022-04-11 17:53:21 1461225468
2022-04-11 17:53:21 33326912000827430
2022-04-11 17:53:21 33326912000827431
2022-06-30 20:25:16 1774796495
2022-06-30 20:25:17 3644757138153474
2022-07-06 10:40:03 3645241416307060
2022-07-06 10:40:03 5672171301314802
2022-07-26 00:00:00 5730052744046899
2022-07-29 17:20:00 5730052763127046
2022-07-29 17:20:00 14107755464138770
2022-08-14 06:40:12 14107755543038090
2022-08-14 06:40:12 19744916779638790
2022-08-17 16:00:04 19747433398195963
2022-08-17 16:00:04 20973009007616032
2022-08-17 17:38:51 20993124881286978
2022-08-17 17:38:51 21000691401433170
2022-08-26 10:36:26 21000691450716350
2022-08-26 10:36:26 24169068668137543
2022-09-01 00:00:00 24189201369196762

2022-10-03 10:11:15 34295779513113914

目前应该是不支持,就是支持代价也会很大,主键变更会导致大量数据搬迁,以前做过数据对比的思路你可以参考下,不知道你的是怎么做的,可以加一个二分查找的判断用shell或者python来做,找到最大值然后除以2取中,然后最小的值到区中值统计下数据量,如果小于10亿那就直接导出,如果大于10亿重复上面的操作,这样保证每次导出的数据小于10亿,如果全部导出就循环;

1 个赞

我现在的方法比较耗时,因前面数据id连续递增,到跳的id时不停增加id值以及对比此id创建日期,这样推断有无空的id,然后在查询起始和结束id不超过一定范围,比如5亿条数据量以内作为一次导出。
select count(id) from xxx where id > 5730055060275318 and id <= 5730055600000000
460307296

select created_time from xx where id = 5730055060275318;
2022-07-19 04:50:39

select created_time from produce_param where id = 5730055600000000;
2022-07-21 06:58:31

https://docs.pingcap.com/zh/tidb/stable/auto-increment#auto_id_cache 如下官方文档也有对id cache解释,但是我们生产的还是测试人员将测试数据传输到生产导致的。

官方说了 业务不要依赖自增id,这个没办法解决的 自增id想连续 你前端只能有一个tidb

1 个赞

只能有一个tidb怎么理解?我的是一套环境里面的库表,只是工厂很多,但都是同一个账户写入的,前期对测试数据没有限制,导致测试数据入库id很大,后面插入数据就随着变大,这样连续反复几次,就出现上述情况,目前已经对生产测试数据做了限制,但是一直在思考可有好的方法能将上面的表数据id重置使其连续。

自增id在tidb里面本来就无法做到连续 你要连续的话只能前端部署一个tidb 3pd 5tikv这种架构

1 个赞

而你只能把表删除重新导入才能让id不那么大

1 个赞

在不就自己使用雪花id 或者其他ID生成器,自增id 也很容易产生热点写,且在频繁插入的情况下可能会出现冲突(我目前遇到了,具体原因不详)

1 个赞

是的,中间插入了个很大的id,自增会跟着最大的往后生成,当前没有办法,就像爱好者说的只能导出重新灌一次数据

1 个赞

当时一个分段对比数据脚本改了一下,就当前的问题你看对你有帮助没:
minid=mysql -h -u -p -e"select min(id) from t"
maxid=select max(id) from t

ksid=$minid
let zjid=($maxid-$ksid)/2
let jzid=$ksid+$zjid
while ture
do
sycount=mysql -h -u -p -e"select count(*) from t where id=>$ksid and id <=$maxid"
if [[ “$sycount” -gt “10” ]];then
count=select count(*) from t where id=>$ksid and id <$jzid
while ture
do
if [[ “$count” -gt “10” ]];then
let zjid=$zjid/2
let jzid=$ksid+$zjid
count=mysql -h -u -p -e"select count(*) from t where id=>$ksid and id <$jzid"
else
echo “select * from t where id=>$ksid and id <$jzid”
let ksid=$jzid
let zjid=($maxid-$ksid)/2
let jzid=$ksid+$zjid
break
fi
done
else
echo “select * from t where id=>$ksid and id <$jzid”
exit
fi
done

1 个赞