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

Quarkus 3.2.0.Final迁移后序列同步异常与主键重复问题求助

问题根因分析与解决建议

根因分析

1. 序列命名问题

Quarkus 3.x升级到了Hibernate 6,而Hibernate 6对Envers的默认序列命名策略做了修改:

  • Hibernate 5(Quarkus 2.x)中Envers默认使用的序列名为info_rev_seq
  • Hibernate 6中改为revinfo_seq
    这就是你遇到第一个报错“找不到public.revinfo_seq”的原因,重命名序列后该问题解决,但也为后续主键冲突埋下伏笔。

2. 主键重复与序列失同步问题

核心原因是Hibernate 6中Envers的REVINFO主键生成策略发生了变更:

  • 在Hibernate 5中,Envers默认依赖PostgreSQL bigserial类型的IDENTITY生成策略,由数据库自动维护序列与表的主键同步
  • Hibernate 6中,Envers默认切换为显式SEQUENCE生成策略,直接操作指定序列生成revision编号
  • 你将原序列info_rev_seq重命名为revinfo_seq后,该序列的当前值远低于REVINFO表中已有的最大rev值(23 vs 54),导致Envers生成的revision编号与表中已存在的主键重复
  • 手动同步序列后再次失同步,大概率是因为部分场景下(如事务回滚、批量审计操作),Envers的序列使用逻辑与数据库序列的原子性生成逻辑不匹配,或者配置中存在allocationSize大于1的情况,导致序列预分配的编号未被全部使用,后续再次生成时出现冲突。

解决建议

1. 强制Envers使用IDENTITY主键生成策略

如果希望继续依赖PostgreSQL bigserial的自动维护逻辑,在application.properties中添加配置:

hibernate.envers.revision_generator.strategy=identity
hibernate.envers.use_revision_entity_with_native_id=true

该配置会让Envers回到Hibernate 5的行为,直接使用数据库原生的IDENTITY生成主键,无需手动维护序列。

2. 修复序列与表的同步并配置正确的序列策略

如果坚持使用SEQUENCE策略:

  • 首先执行SQL将序列值同步到表中最大rev+1(避免立即冲突):
SELECT setval('public.revinfo_seq', (SELECT COALESCE(MAX(rev), 0) + 1 FROM public.revinfo));
  • 然后在application.properties中明确配置序列相关参数:
hibernate.envers.revision_generator.strategy=sequence
hibernate.envers.revision_generator.sequence_name=revinfo_seq
# 分配大小设为1,避免预分配导致的序列浪费与失同步
hibernate.envers.revision_generator.allocation_size=1
  • 如果自定义了RevisionEntity,需要在@RevisionNumber字段上显式指定序列生成器:
@RevisionEntity
public class CustomRevisionEntity extends DefaultRevisionEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "revinfo_seq_gen")
    @SequenceGenerator(
        name = "revinfo_seq_gen",
        sequenceName = "revinfo_seq",
        allocationSize = 1
    )
    @RevisionNumber
    private long rev;

    // 其他字段与逻辑
}

3. 排查事务回滚场景

检查系统中是否存在大量包含审计操作的事务回滚场景:PostgreSQL的序列值在事务回滚时不会回滚,如果Envers在事务中预取了序列值但最终事务回滚,会导致序列值与表中主键出现偏差。这种情况下,要么调整业务逻辑减少不必要的回滚,要么使用IDENTITY策略规避序列预分配的问题。

内容的提问来源于stack exchange,提问作者Fortran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:14:53