暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 选择的并行执行 ..对于使用插入进行更新

ASKTOM 2018-12-18
463

问题描述

嗨,汤姆

我们有一个存储的proc,如下所示:

Proc P1 (p_id in varchar2)
is 
cursor c1 
is 
select a,b,c 
from t1, t2 
where t1.pk = t2.fk 
and t1.id = p_id ;

v_id varchar2(10);

Begin

Open c1 (p_id);
fetch c1 into v_id;
close c1;

If nvl(v_id,0) = 0 then
 insert into t1 (PK, id,...) values(sequence, v_id, .......);
else
 update t1 set some_other_col = some_val
 where t1.id = v_id;
end if;

End;
复制


这个过程是由一些Java API调用的。通常这工作得很好,但是当有2个Java会话并行运行时,如果表中不存在v_id,它会插入重复项。它们实际上不是重复的,因为主键是基于序列的,但是如果我们从id的角度考虑,它是重复的。

为了解决这个问题,如果我们使用FOR UPDATE子句到游标,它是否也有助于插入新的id以及?

收到您的来信真是太好了。非常感谢您的帮助。

致以最诚挚的问候,
阿舒

专家解答

如果每个ID值必须只有一行,有一种方法可以解决这个问题:

对它放置一个独特的约束!

选择更新无济于事。如果要添加新行,则查询将不返回任何内容。所以没有什么可以锁定来停止另一个会话。

其他一些观察结果:

我不明白您为什么要在光标中加入t2。您只是在插入/更新t1。因此,当没有子t2行时,这可能会添加更多重复项。

您可以用合并替换if insert else更新。

所以我会做这样的事情:

create sequence s;
create table t (
  pk int primary key,
  id int unique,
  c1 int
);
 
create or replace procedure p ( 
  p_id int , p_v1 int
) as
begin

  merge into t 
  using ( select p_id id, p_v1 v1 from dual ) s
  on    ( t.id = s.id )
  when not matched then
    insert ( pk, id, c1 )
    values ( s.nextval, s.id, s.v1 )
  when matched then 
    update set c1 = s.v1;
    
end p;
/
复制


如果你在两个并发会话中调用p,你会看到:

第1场会议:

SQL> exec p ( p_id => 1, p_v1 => 1 );

PL/SQL procedure successfully completed.
复制


然后,会话2将被阻止:

SQL> exec p ( p_id => 1, p_v1 => 2 );
复制


直到会话1提交/回滚:

SQL> commit;

Commit complete.
复制


回到第2节:

SQL> exec p ( p_id => 1, p_v1 => 2 );
BEGIN p ( p_id => 1, p_v1 => 2 ); END;

*
ERROR at line 1:
ORA-00001: unique constraint (CHRIS.SYS_C0043990) violated


SQL> exec p ( p_id => 1, p_v1 => 2 );

PL/SQL procedure successfully completed.

SQL> select * from t;

        PK         ID         C1
---------- ---------- ----------
         1          1          2
复制

文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论