GaussDB迁移后应用执行无法正常执行saveOrUpdate
适用范围
数据库引擎版本:GaussDB V2.0-8.103.0
内核引擎版本:505.1.0.SPC0100
实例类型:分布式版
操作系统:麒麟V10-4.19.90-23.8.v2101.ky10.aarch64
开发框架:J2EE-Hibernate
问题概述
使用gs_dump完成GaussDB数据库迁移后,应用正常执行业务时报Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
正常需要插入的数据,没有正常插入。
Hibernate的saveOrUpdate方法保存实例。saveOrUpdate方法要求ID为null时才执行SAVE,在其它情况下执行UPDATE。在保存实例的时候是新增,但你的ID不为null,所以使用的是UPDATE,但是数据库里没有主键相关的值,所以出现异常。
序列Sequence是用来产生唯一整数的数据库对象。序列的值是按照一定规则自增的整数。因为自增所以不重复,因此说Sequence具有唯一标识性。因此,在数据库中Sequence常常被作为主键使用。
问题原因
使用GS_DUMP工具迁移时序列会重新从初始值开始递增,如果业务切换至目标库会导致采用序列做为主键的列值冲突。
解决方案
目标库重置重置每个序列的当前值。
处理过程
1、迁移前收集序列信息
gaussdb=# select * from pg_sequence;
2、重置序列当前值
–检查当前序列值
gaussdb=# select nextval(‘sqlhfxf’);
gaussdb=# select currval(‘sqlhfxf’);
说明:返回当前会话里最近一次nextval返回的数值。如果当前会话还没有调用过指定的sequence的nextval,那么调用currval将会报错。
–重置当前序列值
gaussdb=# select setval('sqlhfxf',5,true);
setval
-------
5
setval(regclass, numeric),设置序列的当前数值。
【小结】进行GaussDB同构或异构迁移时,我们应该检查所有对象,特别时序列这种对业务相对来说比较敏感的对象。