如何配置JPA+MySQL让Long类型自增主键ID按顺序连续生成
根因说明
你当前实体类主键配置的@GeneratedValue(strategy = GenerationType.IDENTITY)策略,完全依赖MySQL数据库自身的自增主键机制生成ID,跳号问题和JPA、业务代码逻辑无关,是你使用的Heroku平台ClearDB MySQL插件的默认配置导致:
- ClearDB默认将自增偏移量参数
auto_increment_offset设置为4,因此第一条插入记录的起始ID为4 - ClearDB默认将自增步长参数
auto_increment_increment设置为10,因此后续每插入一条记录ID递增10,最终出现4、14、24这类固定间隔跳号的现象
ClearDB默认做这个配置是因为其采用多主集群高可用架构,通过设置不同的自增偏移量+固定步长,可以避免不同主节点同时写入时生成重复主键,属于托管数据库的常规高可用配置。
处理方案
推荐方案(生产环境优先选择)
无需修改任何配置,接受现有ID生成规则即可。
数据库主键的核心设计要求是全局唯一,从来没有强制连续的规范。业务层不要依赖主键的连续有序性,现有跳号现象不会影响数据一致性、查询性能,反而连续自增ID在高并发写入场景更容易引发行锁竞争、主键热点问题,也容易被外部通过ID遍历爬取全量业务数据。
临时修改方案(仅适用于测试环境、强依赖连续ID的场景)
如果你确实需要生成1、2、3顺序的连续ID,且可以接受托管平台配置重置、多主切换主键重复的风险,可以按以下步骤修改:
- 通过MySQL客户端连接到你的ClearDB实例,先执行命令确认当前自增参数配置:
SHOW VARIABLES LIKE 'auto_increment%';
执行后可以看到auto_increment_offset值为4、auto_increment_increment值为10,和你观察到的跳号现象完全匹配。
2. 针对你的业务表单独修改自增起始值:
ALTER TABLE `user` AUTO_INCREMENT = 1;
- 注意:由于ClearDB普通账号没有数据库SUPER权限,无法全局修改自增步长和偏移量参数,仅修改单表自增起始值后,后续平台侧参数巡检、主节点切换都可能把配置重置回默认值,生产环境不建议使用该方案。
额外代码优化建议
你当前Service层的代码存在冗余配置:同时使用@AllArgsConstructor、@NoArgsConstructor注解的前提下,不需要额外给UserRepository字段加@Autowired注解,Spring会自动通过构造器完成注入,多余注解可以删除。
内容的提问来源于stack exchange,提问作者Syan

