Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.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
Java 我可以在Oracle中进行原子合并吗?_Java_Oracle_Concurrency_Merge_Weblogic - Fatal编程技术网

Java 我可以在Oracle中进行原子合并吗?

Java 我可以在Oracle中进行原子合并吗?,java,oracle,concurrency,merge,weblogic,Java,Oracle,Concurrency,Merge,Weblogic,我在一个WebLogic集群中运行了几个J2EE应用程序实例 在某些情况下,这些应用程序会进行合并,将记录插入或更新到后端Oracle数据库中。合并检查是否存在具有指定主键的行。如果有,请更新。如果没有,请插入 现在假设两个应用程序实例希望插入或更新主键为100的行。假设该行不存在。在合并的“检查”阶段,它们都看到行不在那里,因此都尝试插入。然后我得到一个唯一的密钥约束冲突 我的问题是:Oracle中是否存在原子合并?我正在寻找与插入具有类似效果的东西。。。用于PL/SQL中的更新,但我只能从我

我在一个WebLogic集群中运行了几个J2EE应用程序实例

在某些情况下,这些应用程序会进行合并,将记录插入或更新到后端Oracle数据库中。合并检查是否存在具有指定主键的行。如果有,请更新。如果没有,请插入

现在假设两个应用程序实例希望插入或更新主键为100的行。假设该行不存在。在合并的“检查”阶段,它们都看到行不在那里,因此都尝试插入。然后我得到一个唯一的密钥约束冲突

我的问题是:Oracle中是否存在原子合并?我正在寻找与插入具有类似效果的东西。。。用于PL/SQL中的更新,但我只能从我的应用程序执行SQL

编辑:我不清楚。我正在使用MERGE语句,但此错误仍在发生。问题是,只有“修改”部分是原子的,而不是整个合并

编辑:获得这种防水效果的唯一方法是插入、捕获dup\u val\u on\u索引异常并对其进行适当处理(更新,或者插入其他记录)。这可以很容易地用PL/SQL完成,但不能使用它

你也在寻找解决办法。您能在Java中捕获dup_val_on_索引并再次发布额外的更新吗

在伪代码中:

try {
  // MERGE
}
catch (dup_val_on_index) {
  // UPDATE
}

我很惊讶MERGE会以您描述的方式运行,但我还没有充分使用它来说明是否应该这样做


在任何情况下,您都可以让希望执行合并的事务将其隔离级别设置为可序列化。我认为这可能会解决您的问题。

这不是合并本身的问题。问题在于你的申请。考虑这个存储过程:

create or replace procedure upsert_t23 
    ( p_id in t23.id%type
      , p_name in t23.name%type )
is
    cursor c is
        select null 
        from t23
        where id = p_id;
    dummy varchar2(1);
begin
    open c;
    fetch c into dummy;
    if c%notfound then
        insert into t23 
            values (p_id, p_name);
    else
        update t23
             set name = p_name
             where id = p_id;
    end if;
 end;
因此,这是T23上的合并的PL/SQL等价物。如果两个会话同时调用它会发生什么

SSN1>  exec upsert_t23(100, 'FOX IN SOCKS')

SSN2>  exec upsert_t23(100, 'MR KNOX')
SSN1首先到达那里,没有找到匹配的记录并插入一条记录。SSN2在SSN1提交之前第二个到达,没有找到任何记录,插入记录并挂起,因为SSN1在唯一索引节点上有一个100的锁。当SSN1提交时,SSN2将抛出DUP\u VAL\u ON\u索引冲突

MERGE语句的工作方式完全相同。这两个会话都将在(t23.id=100)上检查
,但找不到它,然后沿着插入分支进行操作。第一节将成功,第二节将投掷ORA-00001

处理这个问题的一种方法是引入悲观锁定。在UPSERT_T23程序开始时,我们锁定表格:

...
lock table t23 in row shared mode nowait;
open c;
...
现在,SSN1到达,抓起锁,像以前一样继续。当SSN2到达时,它无法获得锁,因此它立即失败。这对第二个用户来说是令人沮丧的,但至少他们没有挂断,而且他们知道其他人正在处理相同的记录


INSERT没有与SELECT等效的语法。。。用于更新,因为没有可选择的内容。所以对于MERGE也没有这样的语法。您需要做的是在发出合并的程序单元中包含LOCK TABLE语句。这对您是否可行取决于您使用的框架

第二个会话中的MERGE语句在该会话提交之前无法“查看”第一个会话所做的插入。如果减少交易的规模,则发生这种情况的概率将降低

或者,您可以对数据进行排序或分区,以便将给定主键的所有记录提供给同一会话。像“主键mod N”这样的简单函数应该平均分配到N个会话


顺便说一句,如果两条记录具有相同的主键,则第二条记录将覆盖第一条记录。听起来有点奇怪。

好吧,周末过后我会再进一步调查的!您能够使用PL/SQL吗?我发现的第一件事表明,带有异常处理的插入(当dup_val_在_索引上时,然后更新)是获得这种防水性的唯一方法。我也在考虑这个选项。当使用JPA时,在Java中到达catch部分意味着事务已经标记为回滚,没有机会提交更新@MartinSchapendonk-捕获的是什么样的异常?SQLException?合并是原子的。它要么作为一个完整的工作单元工作,要么失败。您看到的是Oracle实施多版本一致性的结果。听起来你在寻找一些东西来实现多重合并?您可以尝试使用Oracle的seralizable事务,但这可能只是将错误从唯一键约束更改为无法序列化事务错误。My database/multi-thread vocab可能是错误的。我的理解是“作为一个完整的工作单元工作或失败”被称为事务性的。原子的意思是,在处理另一个合并时,不能进行任何合并。关于序列化合并,我得读一下。谢谢。@Russell,原子性只是事务的一个属性。它确实意味着作为一个整体的成功或失败。例如,请参阅:以及。您可以获得新副本的主键来自何处?啊,很好地概括了ACID。谢谢自从我上次使用数据库以来,很久以前我就没有听说过这个。主键来自一个我无法控制的外部来源。谢谢,这完美地表达了我在问题中试图解释的内容。关于如何处理这个问题,锁不是PL/SQL的一部分吗?我正在寻找一种使用Oracle SQL的变通方法/解决方案,可以从我的应用程序中调用。我不是真的在寻找一个插入,这相当于选择。。。更新(尽管我说的方式可能会让你这么想)。我只是想知道是否有任何方法可以通过MERGE语句(因此问题的标题)锁定正在合并的行。当然,感谢您提供了全面的答案和知识:)在行共享(而不是行共享)中锁定表几乎没有任何效果