Spring Boot与C++共用Oracle序列引发主键冲突问题排查
SpringBoot与C++应用共用Oracle序列生成主键时的值差异及主键冲突问题
背景
两个应用(SpringBoot应用、C++应用)共用Oracle序列SEQUENCE_A,为同一张表TABLE-A生成主键。序列的创建语句如下:
CREATE SEQUENCE SEQUENCE_A START WITH 1 INCREMENT BY 1 ORDER;
按设计,该序列应从1开始每次递增1,不循环,多应用同时请求时应生成连续的唯一值。
各应用的主键生成实现
SpringBoot应用(ORM方式)
通过JPA实体映射配置主键生成,代码如下:
@Entity @Table(name = "TABLE-A") public class TableAEntity implements Serializable { private static final long serialVersionUID = 1234...L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "table-a_generator") @SequenceGenerator(name = "table-a_generator", sequenceName = "SEQUENCE_A", allocationSize = 1) @Column(name = "ID", nullable = false) private Long id; ... }
C++应用(直接SQL插入)
正常情况下C调用SpringBoot完成插入,当SpringBoot无响应或宕机60秒后,C自行执行插入SQL,通过序列生成主键:
INSERT ALL INTO TABLE-A(ID, NAME) VALUES(SEQUENCE_A.NEXTVAL, '%s') INTO TABLE-A-LOG(ID, TABLE-A_ID, SUCCEEDED) VALUES(SEQUENCE_B.NEXTVAL, SEQUENCE_A.CURRVAL, 0) SELECT * FROM DUAL", name
异常现象
- 生产环境偶尔触发
ORA-0001主键唯一约束违反,推测是某应用复用了已存在的主键值 - 数据记录观察:
- SpringBoot应用生成的主键为4位数,最近三个值为4122、4123、4124
- C++应用生成的主键为2位数,最近三个值为21、41、61
- 直接查询序列值:
该结果与C++应用获取的序列值一致,但SpringBoot生成的值远高于此SELECT SEQUENCE_A.NEXTVAL FROM DUAL; -- 返回62 SELECT SEQUENCE_A.CURRVAL FROM DUAL; -- 返回62 - 查询序列属性:
结果:SELECT MIN_VALUE, MAX_VALUE, INCREMENT_BY, CYCLE_FLAG, CACHE_SIZE, LAST_NUMBER FROM ALL_SEQUENCES WHERE SEQUENCE_NAME = 'SEQUENCE_A';MIN_VALUE|MAX_VALUE |INCREMENT_BY|CYCLE_FLAG|CACHE_SIZE|LAST_NUMBER| ---------+----------------------------+------------+----------+----------+-----------+ 1|9999999999999999999999999999| 1|N | 20| 101|
疑问
为何两个应用使用同一序列生成的主键值差异巨大?SpringBoot应用为何生成远高于Oracle返回的序列值?
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

