使用oracle数据库。以下是我认为SQLException是如何发生的。。。
假设我有两个并行运行的服务实例。他们都做以下事情:
- 查询缓存(B)以查看Person是否存在
- 如果人员存在,但已过期或不存在=对主数据库进行查询(a)
- 如果在数据库(A)中找到人员,而之前在缓存(B)中未找到人员。INSERT,否则,如果之前在缓存中发现人员,但其UPDATE缓存已过期
我使用以下代码来做出决定,基于之前的查询来缓存B.
void insertOrUpdate(RegistryPersonMo person) {
if (person.getId() == null) {
insertPerson(person);
} else {
updatePerson(person);
}
}
并使用Spring JDBC插入:
void insertPerson(RegistryPersonMo person) {
Number id = insertInto("PERSON_REGISTRY", "RAAMAT").usingGeneratedKeyColumns("ID").executeAndReturnKey(usingParameters(person));
if (id != null) {
person.setId(id.longValue());
}
}
当服务的两个实例已经完成了对缓存的查询(B),但没有找到人员(null)时,实际问题就会出现。然后一个实例执行INSERT,因为数据不存在。另一个在尝试执行相同操作时获得SQLException,因为具有唯一约束的条目已经存在。
有人知道最佳\标准解决方法是什么吗?我有一些想法:
- 锁定行的读数,直到插入完成。我可以用Spring来做这件事吗
- 使用replace或insert替换为ignore。仍在学习,这些有什么负面影响吗
请记住,我希望使用Spring并尽可能地自动化查询。。
我认为在这种情况下忽略唯一约束异常是可以的。是的,这是比赛条件,但达到了预期的一个期望的结果,插入了记录。也许记录它可以断言这种情况发生的频率。
锁定或事务序列化可以解决这个问题,但在我看来,在这种情况下没有多大意义。