Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Oracle合并-唯一密钥上的约束冲突_Sql_Oracle_Oracle11g - Fatal编程技术网

Sql Oracle合并-唯一密钥上的约束冲突

Sql Oracle合并-唯一密钥上的约束冲突,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我在Oracle11g中有这个表 TABLE: ORDER_LOCK Name Null Type ---------------------- -------- ---------- ORDER_ID NOT NULL NUMBER(10) [PRIMARY KEY] ORDER_REF_ID NUMBER(10)

我在Oracle11g中有这个表

TABLE: ORDER_LOCK
Name                   Null     Type                
---------------------- -------- ----------          
ORDER_ID                     NOT NULL NUMBER(10) [PRIMARY KEY] 
ORDER_REF_ID                 NUMBER(10)          [UNIQUE KEY]
ORDER_MSG_SENT                   NUMBER(1)          


merge into ORDER_LOCK al 
using ( select ? ORDER_REF_ID, ? ORDER_MSG_SENT from dual ) t 
on (al.ORDER_REF_ID = t.ORDER_REF_ID) 
when not matched then 
    insert (ORDER_ID, ORDER_REF_ID, ORDER_MSG_SENT) 
    values (ORDER_LOCK_SEQ.nextval, t.ORDER_REF_ID, t.ORDER_MSG_SENT)
我正在使用我的应用程序(Java)中的上述合并。合并调用发生在多个线程中。代码一直运行良好,但昨天我们在唯一键“ORDER\u REF\u ID”上发现了一个约束冲突(ORA-00001)

Merge语句有问题吗?或者,当上述Merge语句可能导致违反约束时,是否存在任何特定的场景

谢谢


布什格尔

< P>如果你有两个会话(在你的例子中是java线程),试图插入相同的OrthyRefID。请考虑下面的场景:

1) 会话1执行此合并语句(不提交):

2) 会话2启动相同的合并语句:

merge into ORDER_LOCK al 
using ( select 1 ORDER_REF_ID, sysdate ORDER_MSG_SENT from dual ) t 
on (al.ORDER_REF_ID = t.ORDER_REF_ID) 
when not matched then 
    insert (ORDER_ID, ORDER_REF_ID, ORDER_MSG_SENT) 
    values (ORDER_LOCK_SEQ.nextval, t.ORDER_REF_ID, t.ORDER_MSG_SENT);
(这将尝试插入行,因为会话2没有“看到”来自会话1的未提交更改。会话2将被阻止,因为它正在等待会话1持有的锁):

3) 第1次会议提交

=>会话2现在尝试执行插入,这将引发ORA-00001:唯一约束冲突,因为ORDER_REF_ID 1已经存在

更新


为了解决这个问题,我建议您修改您的应用程序,并在Java线程和ORDER_REF_ID之间引入某种相似性-每个ORDER_REF_ID应该“属于”一个线程,该线程应该专门插入/更新其ORDER\u REF\u ID的数据。

您是否检查了两个或多个线程是否可以尝试插入相同的ORDER\u REF\u ID?谢谢Frank。Merge语句所做的插入是有条件的,即当在表中找不到ORDER\u REF\u ID时,它会进行插入。如果在表中找到ORDER\u REF\u ID,则不会执行插入操作。我是不是遗漏了什么?合并是专门为避免ORA-00001而实现的。如果两个会话同时尝试插入,则无法避免ORA-00001,除非将事务隔离级别更改为“读取未提交”(绝对不推荐)。如果合并遇到ORA-00001,最明智的做法是回滚并重新尝试该操作-如果第一个会话在此期间已提交,则第二个会话不会尝试执行插入。您对此有何看法?
merge into ORDER_LOCK al 
using ( select 1 ORDER_REF_ID, sysdate ORDER_MSG_SENT from dual ) t 
on (al.ORDER_REF_ID = t.ORDER_REF_ID) 
when not matched then 
    insert (ORDER_ID, ORDER_REF_ID, ORDER_MSG_SENT) 
    values (ORDER_LOCK_SEQ.nextval, t.ORDER_REF_ID, t.ORDER_MSG_SENT);