0

在并发请求的情况下,我遇到了重复插入的以下问题。

我有两张桌子:

create table tbl (
  val varchar2(1000)
);

create table tbl2 (
  val varchar2(1000)
);

tbl2只有在表tbl为空的情况下,我才需要在表中插入一些值。因此,在我的 Java 代码中,我使用隔离级别 = READ COMMITED 进行事务处理:

//start transaction
int result = jdbcTemplate.queryForInt("select count(*) from tbl");
if (result == 0) {
  int update = jdbcTemplate.update("insert into tbl2(val) values(?)", "di" + UUID.randomUUID().toString());
}
//end transaction

这里的问题是:实际上有人可以在if (result == 0)我的更新语句之间插入数据。所以我会有重复的条目。

我的例子过于简单,但我的实际情况要复杂得多,但基本思想是一样的:我需要在插入之前从 Javacode 内部进行几次选择。

那么,如何避免这种情况(我对 db 端解决方案和 java 端解决方案感兴趣)?

PS数据库是Oracle。

4

2 回答 2

2

我认为处理这种情况的最佳方法可能是在数据库级别。您可以使用如下查询:

insert into tbl2 values(xx) where not exists (select 1 from tbl1)

所以你的查询可能会变成这样

int update = jdbcTemplate.update("insert into tbl2(val) values(?) where not exists (select 1 from tbl1)", "di" + UUID.randomUUID().toString());
于 2012-07-13T23:26:10.763 回答
1

不太清楚你为什么要做你正在做的事情,但你可以先锁定桌子。

LOCK TABLE tbl IN SHARE MODE;

记得提交;释放锁。

于 2012-07-13T22:52:09.867 回答