mybatis-plus获取auto_random id 失败,生成的值太大了

为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:

【概述】 场景 + 问题概述
新增数据时报错大意是返回的新ID数值太大了,long类型放不下.

【应用框架及开发适配业务逻辑】
mybatis-plus3. 单表新增操作, 主键设为auto_random , 实体类主键标注:

@TableId(value = "pasting_id", type = IdType.AUTO)
    private Long pastingId;

该类型会自动获取新增后返回的ID并设置到对应属性, insert操作后报错,返回的id长度有20多位了,long类型放不下

【TiDB 版本】 8.5.3

另外这个ID限制实在不方便,传统数据库都是顺序id更有效, 迁移数据时非常不方便

  1. 紧急修复:优先排查 TiDB 表结构(字段类型是否为 BIGINT)和 auto_random 起始值(是否超出 Long 范围),这是解决 “ID 过大” 的直接原因;
  2. 适配优化:配置 MyBatis-Plus 的 TiDB 方言,确保 ID 获取逻辑正常;
  3. 长期方案:若需 “顺序 ID + 易迁移”,推荐改用 MyBatis-Plus 的 ASSIGN_ID(雪花算法),彻底摆脱对 TiDB auto_random 的依赖,同时满足传统自增 ID 的使用习惯。

雪花算法也是顺序增长的,同样会有写入热点问题吧

https://docs.pingcap.com/zh/tidb/stable/auto-increment/


在 TiDB 8.5.3 中,AUTO_INCREMENT + AUTO_ID_CACHE 的自增 ID 表现和传统 MySQL 有明显差异。
这是因为 TiDB 使用的是 分布式全局唯一 ID 分配机制(AutoID / RowID),由 PD 统一调度分配,保证多 TiDB 实例下的全局唯一性与高并发安全

:gear: 原因分析

在 TiDB 中:

  • 自增 ID 不是单机递增,而是带有高位时间戳 + 节点信息 + 自增序列的复合结构;
  • 所以生成的 ID 会是 18~20 位左右的大数
  • 即使设置了 AUTO_ID_CACHE 1,TiDB 仍然从 PD 获取全局分配的 ID 段;
  • 因此 ID 不仅数值大,而且在多节点并发下也不会严格连续。

这种设计是出于 分布式一致性和扩展性 的考虑,而非异常。

实际影响

  1. Java long 溢出问题
    TiDB 的 ID 已经接近甚至超过 Long.MAX_VALUE (9,223,372,036,854,775,807) 的范围。
    在 Java 应用中如果使用 long 类型接收,会发生溢出或抛出异常。
    建议改为 StringBigInteger 存储 ID。
    ORM 框架(如 MyBatis、JPA)也建议在实体类中把主键定义为 String

  2. JavaScript 精度丢失
    JS 的 Number 类型是 64 位双精度浮点数(最大安全整数约为 2^53-1 ≈ 9.0e15),
    而 TiDB 的 ID 经常超过这个范围,直接在前端显示会精度丢失、四舍五入
    前端应以字符串格式接收和展示主键 ID,禁止强转为数字。

可行解决方案

  • 如确需顺序 ID
    可改用:

    CREATE TABLE t(
        id BIGINT PRIMARY KEY AUTO_INCREMENT
    ) SHARD_ROW_ID_BITS = 0 PRE_SPLIT_REGIONS = 0;
    

    或使用自定义序列、外部发号器等方式控制递增(建议使用UUIDv7)。


总结

TiDB 的 AUTO_INCREMENT ID 设计目标是全局唯一 + 高并发安全 + 分布式扩展性
不是传统意义上的“连续整数主键”。

所以出现大数 ID 是比较正常现象,
但在 Java和JavaScript 等交互要注意类型溢出和精度问题,
统一用 字符串 存储和传输 ID 才是安全做法。

将其调整为AUTO_RANDOM(5, 53),不知道这样会不会有其他影响

改用 auto_increment 主键