대상 총계를 유지하고 기존 값과 새 값의 차이를 반환하는 Oracle 데이터베이스에서 업데이트/삽입을 수행하는 PL/SQL 기능이 있습니다. 다중 스레드는 결코 실패하지와 단위 테스트에서 예상대로이 작동Oracle 및 PL/SQL을 사용한 삽입 또는 업데이트
FUNCTION calcTargetTotal(accountId varchar2, newTotal numeric) RETURN number is
oldTotal numeric(20,6);
difference numeric(20,6);
begin
difference := 0;
begin
select value into oldTotal
from target_total
WHERE account_id = accountId
for update of value;
if (oldTotal != newTotal) then
update target_total
set value = newTotal
WHERE account_id = accountId
difference := newTotal - oldTotal;
end if;
exception
when NO_DATA_FOUND then
begin
difference := newTotal;
insert into target_total
(account_id, value)
values
(accountId, newTotal);
-- sometimes a race condition occurs and this stmt fails
-- in those cases try to update again
exception
when DUP_VAL_ON_INDEX then
begin
difference := 0;
select value into oldTotal
from target_total
WHERE account_id = accountId
for update of value;
if (oldTotal != newTotal) then
update target_total
set value = newTotal
WHERE account_id = accountId
difference := newTotal - oldTotal;
end if;
end;
end;
end;
return difference
end calcTargetTotal;
:
는 여기에 지금까지 가지고있는 코드입니다. 우리가 본 라이브 시스템에로드 할 때
그러나이 스택 추적이처럼 보이는 실패 :
ORA-01403: no data found
ORA-00001: unique constraint() violated
ORA-01403: no data found
(그들은 문맥 의미가 있기 때문에 내가 제거한) 라인 번호 확인이 첫 번째 업데이트 데이터가 없어서 실패하고, 고유성으로 인해 삽입이 실패하며, 두 번째 업데이트가 불가능한 데이터없이 실패합니다.
다른 스레드에서 읽은 내용은 MERGE 문도 원자 적이지 않으며 비슷한 문제가 발생할 수 있습니다.
아무도 아이디어가 발생하지 않도록 방지하는 방법이 있습니까?
하나의 열 (accountID)에 대한 고유 색인 만 있습니까? 또는 설명을 단순화하기 위해 표시하지 않는 두 번째 열이 있습니까? – redcayuga
고유 제한 조건은 어떻게 정의됩니까? 고유 색인? 명시 적 고유 제한 조건이있는 고유하지 않은 색인? 명시 적 고유 제한 조건이 정의되면 연기가 가능합니까? – redcayuga