我有一些代码在多台机器上运行,并访问Oracle数据库。我通过锁定行将此数据库(以及其他内容)用作不同计算机之间的同步对象。
我遇到的问题是,当我的进程启动时,数据库中还没有任何东西可以依赖于同步,并且我的进程得到关于unique constraint violated
的oracle异常,因为它们都试图同时插入
我现在的解决方案是捕获该精确异常并忽略它,但我真的不喜欢在我的应用程序的正常工作流程中抛出异常。
有没有更好的方法在数据库中以原子方式“测试和插入”?插入行时锁定整个表/分区是不可接受的解决方案。
我检查merge into
,认为这是我的解决方案,但它会产生同样的问题。
答案 0 :(得分:4)
您可能希望使用DBMS_LOCK,它允许用户应用程序代码实现与Oracle数据库锁定行和其他资源时相同的锁定模型。您可以创建类型为'UL'(用户锁定)的队列,并定义资源名称,然后将多个会话锁定到其内容,而不依赖于某个表中的数据。它支持独占锁和共享锁,因此,您有一些可以并发运行的进程(如果它们采用共享锁)或其他独占运行的进程(如果它们采用独占锁),它们将自动在共享锁后面排队(如果有的话)由其他类型的流程等持有
这是一个非常灵活的锁定模型,您无需依赖任何表中的任何数据来实现它。
请参阅Oracle PL / SQL包和类型参考,了解DBMS_LOCK package上的完整独家新闻。
希望有所帮助。
答案 1 :(得分: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提交或回滚。我不知道这种机制是否符合你的要求。