문제

Oracle에 연결된 웹 앱에서 작업하고 있습니다. Oracle에는 "활성화 된"열이있는 테이블이 있습니다. 한 번만이 열만 설정할 수 있습니다. 이를 강화하기 위해 Java에서 직렬화 된 격리 수준을 사용하고 있지만 "거래 할 수 없음"오류가 발생하여 그 이유를 해결할 수 없습니다.

우리는 헌신적 인 독서 수준이 일을 할 것인지 궁금했습니다. 그래서 내 질문은 이것입니다.

다음 SQL과 관련된 거래가있는 경우 :

SELECT *
FROM MODEL;

UPDATE MODEL
SET ACTIVATED = 0;

UPDATE MODEL
SET ACTIVATED = 1
WHERE RISK_MODEL_ID = ?;

COMMIT;

이러한 트랜잭션 중 하나 이상이 동시에 실행할 수 있다는 점을 감안할 때, 하나 이상의 모델 행이 활성화 된 플래그를 1으로 설정할 수 있습니까?

모든 도움이 감사하겠습니다.

도움이 되었습니까?

해결책

솔루션이 작동해야합니다. 첫 번째 업데이트는 전체 테이블을 잠그게합니다. 다른 트랜잭션이 완료되지 않으면 업데이트가 대기됩니다. 두 번째 업데이트는 테이블을 잠그고 있기 때문에 하나의 행만 값 1을 갖도록 보장합니다 (그러나 삽입 문을 방해하지는 않습니다).

또한 행에 RISK_MODEL_ID 존재합니다 (또는 트랜잭션이 끝날 때 '1'의 값이 0 인 경우).

동시 삽입 설명을 방지하려면 자물쇠 테이블 (독점 모드).

다른 팁

Oracle이 활성화 된 플래그가 1으로 설정된 1 행만 사용하는 제약 조건을 처리하기 위해 고유 한 기능 기반 색인을 사용하는 것을 고려할 수 있습니다.

CREATE UNIQUE INDEX MODEL_IX ON MODEL ( DECODE(ACTIVATED, 1, 1, NULL));

이것은 플래그를 1으로 설정하는 행이 하나 이상 중지되지만 플래그가 1으로 설정된 한 행이 항상 있다는 것을 의미하지는 않습니다.

원하는 것은 한 번에 하나의 트랜잭션 만 실행할 수 있도록하는 것이면 FOR UPDATE 통사론. 잠금이 필요한 단일 행이 있기 때문에 이것은 매우 효율적인 접근법입니다.

declare
    cursor c is 
        select activated
        from model
        where activated = 1
        for update of activated;
    r c%rowtype;
begin
    open c;
    --  this statement will fail if another transaction is running
    fetch c in r;
    ....
    update model
    set activated = 0
    where current of c;

    update model
    set activated = 1
    where risk_model_id = ?;

    close c;

    commit;
end;
/

그만큼 commit 자물쇠를 해방시킵니다.

기본 동작은 행이 해제 될 때까지 기다리는 것입니다. 그렇지 않으면 우리는 지정할 수 있습니다 NOWAIT,이 경우 현재 활성 행을 업데이트하려는 다른 세션은 즉시 실패하거나 다음을 추가 할 수 있습니다. WAIT 폴링 시간이있는 옵션. NOWAIT 교수형의 위험을 절대적으로 피하도록 선택하는 옵션이며, 다른 사람이 알고 싶은 테이블을 업데이트하고 있음을 사용자에게 알릴 수있는 기회를 제공합니다.

이 접근법은 테이블의 모든 행을 업데이트하는 것보다 훨씬 확장 가능합니다. WW가 표시된대로 함수 기반 색인을 사용하여 한 행만이 활성화 될 수 있다는 규칙을 시행합니다. = 1.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top