You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.3.0 搭配MySQL 8出现异常自增问题

Spring Data MySQL中user_seq序列仅前两次自增的原因分析

问题场景

  • 使用Spring官方示例项目gs-accessing-data-mysql-complete
  • 通过Postman调用接口插入User对象:
    http://localhost:8080/demo/add?name=paco&email=paco@gmail.com
    
  • 现象:user_seq表仅前两次插入时每次自增50,后续插入不再触发序列的查询/更新操作,直接完成数据插入
  • 对应Hibernate执行日志:
    Hibernate: select next_val as id_val from user_seq for update
    Hibernate: update user_seq set next_val= ? where next_val=?
    Hibernate: insert into user (email,name,id) values (?,?,?)
    Hibernate: select next_val as id_val from user_seq for update
    Hibernate: update user_seq set next_val= ? where next_val=?
    Hibernate: insert into user (email,name,id) values (?,?,?)
    Hibernate: insert into user (email,name,id) values (?,?,?)
    Hibernate: insert into user (email,name,id) values (?,?,?)
    
  • 接口实现代码:
    @PostMapping(path="/add") // Map ONLY POST Requests
    public @ResponseBody String addNewUser (@RequestParam String name
                , @RequestParam String email) {
        // @ResponseBody means the returned String is the response, not a view name
        // @RequestParam means it is a parameter from the GET or POST request
        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "Saved";
    }
    

原因解析

这是Hibernate的序列ID预分配优化策略导致的,具体逻辑:

  1. MySQL本身不支持原生数据库序列(Sequence),当Hibernate使用GenerationType.AUTO或GenerationType.SEQUENCE作为ID生成策略时,会自动创建user_seq表模拟序列行为,以此实现跨数据库的ID生成兼容性。
  2. 为了减少数据库交互提升性能,Hibernate默认会一次性预分配50个ID(由allocationSize参数控制,默认值为50):
    • 第一次插入时,Hibernate查询user_seq获取当前序列值,将序列值直接增加50,然后使用预分配批次中的第一个ID完成插入。
    • 若第二次插入处于新的会话或应用重启场景,之前预分配的ID无法复用,Hibernate会再次查询user_seq获取当前值,更新序列值+50,预分配新的ID批次。
    • 后续插入会直接使用预分配好的剩余ID,无需再操作user_seq表,因此不会再触发序列的查询和更新。

user_seq机制是否半废弃?

并没有半废弃,它是Hibernate为跨数据库兼容设计的序列模拟方案:

  • 当使用GenerationType.SEQUENCE策略时,Hibernate会根据数据库类型自动适配:在PostgreSQL、Oracle等支持原生序列的数据库中直接使用原生序列;在MySQL这类不支持的数据库中,就会通过user_seq这类表模拟序列。
  • 如果更倾向于使用MySQL原生自增特性,可以将ID生成策略改为GenerationType.IDENTITY,此时Hibernate会直接依赖MySQL的AUTO_INCREMENT,不再创建和使用user_seq表。

内容的提问来源于stack exchange,提问作者Raul Lapeira Herrero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:47:07