2

我有一些代码在多台机器上运行,并访问 Oracle 数据库。我通过锁定行将此数据库(除其他外)用作不同机器之间的同步对象。

我遇到的问题是,当我的进程启动时,数据库中还没有任何东西可以依赖于同步,并且我的进程得到了 oracle 异常,unique constraint violated因为它们都尝试同时插入。

我现在的解决方案是捕获那个精确的异常并忽略它,但我真的不喜欢在我的应用程序的正常工作流程中抛出异常。

有没有更好的方法在数据库中原子地“测试和插入”?插入行时锁定整个表/分区不是可接受的解决方案。

我检查了一下merge into,认为这是我的解决方案,但它产生了同样的问题。

4

2 回答 2

4

您可能希望使用 DBMS_LOCK,它允许用户应用程序代码实现与 Oracle 数据库在锁定行和其他资源时相同的锁定模型。您可以创建一个类型为“UL”(用户锁定)的队列,并定义一个资源名称,然后将多个会话锁定到他们的核心内容,而不依赖于某个表中的数据。它同时支持独占锁和共享锁,因此,您有一些可以并发运行的进程(如果它们使用共享锁)或其他独占运行的进程(如果它们使用独占锁),它们将自动在共享锁后面排队(如果有的话)由其他类型的进程等持有。

这是一个非常灵活的锁定模型,你不需要依赖任何表中的任何数据来实现它。

有关DBMS_LOCK 包的完整信息,请参阅 Oracle PL/SQL 包和类型参考。

希望有帮助。

于 2012-09-05T12:58:16.413 回答
2

如果您的 PK 受非唯一索引监管,您不会立即收到错误,请考虑:

<<SESSION 1>>
SQL> create table afac (
  2     id number,
  3     constraint afac_pk primary key (id) 
  4        deferrable /* will cause the PK to be policed by a non-unique index */
  5  );

Table created.

SQL> insert into afac values (1);

1 row created.

<<SESSION 2>>    
SQL> insert into afac values (1); /* Will cause session 2 to be blocked */

会话 2 将被阻止,直到会话 1 提交或回滚。我不知道这种机制是否与您的要求兼容。

于 2012-09-05T13:30:55.067 回答