2017-02-05 7 views
4

무작위 방식으로 값 튜플을 연결하고 동시성 제약으로 인해 트랜잭션을 실패 할 가능성이없는 방법을 찾고 있습니다.SQL 병합을 원자 적으로 실행하는 방법이 있습니까?

편집해야하는 표에는 UUID로 설명해야하는 몇 가지 값이 들어 있습니다. 이 예제에서 테이블의 이름은 foo이며 barqux 두 개의 문자열 열이 하나의 필드 uuid을 가리키는 것으로 선언됩니다. (bar, qux)은 테이블 전체에서 고유해야합니다. UUID는 본질적으로 고유합니다.

는 SQL은 (오라클 12C 사용) 원자 적으로 다음과 같은 일을 할 수 있는지 궁금해 : 내 데이터베이스의 쿼리의 결과로

MERGE INTO foo a 
    USING (SELECT bar, qux FROM foo b 
    ON b.bar = 'a' and b.qux = 'b' 
WHEN NOT MATCHED THEN INSERT (a.bar, a.qux, a.uuid) 
    VALUES ('a', 'b', 'some-uuid'); 

SELECT uuid FROM foo WHERE bar = 'a' and qux = 'b'; 

을, 나는 (bar, qux)가 임의의 UUID와 연결되는 튜플을 원하는 . 이 UUID는 모든 동시 트랜잭션에 대해 동일해야하며 다른 (임의의) UUID를 동시에 삽입하므로 경쟁하는 요청이 실패하지 않기를 바랍니다.

배경으로 :이 삽입은 대부분 서로 독립적이지 않지만 값이 일치하지 않아야하는이 공유 된 식별자 테이블을 가지고있는 오랜 기간 실행되는 트랜잭션의 일부입니다. 많은 프로그래밍 언어가 CAS를 제공하며,이 경우에 내가하려는 것이지만 SQL의 smilar 기능을 알지 못합니다. 더러운 허용하는 것은 해결책이 될 것입니다 (커밋되지 않은 격리 수준을 읽어)를 읽고 있지만 병합 문이 경우 다른 트랜잭션 원자와 볼 경우 내가 아무 생각이없는 경우

하나 개의 아이디어로서, 궁금하네요. (Oracle에서는 불가능) 데이터베이스는 JDBC를 통해 액세스되지만 잠재적으로 여러 VM 노드에서 액세스됩니다.

+2

오라클은 커밋되지 않은 읽기를 허용하지 않습니다. –

+0

얼마나 자주 충돌을 예상합니까?너무 자주 사용하지 않으면 테이블을 쿼리하는 함수 인 (bar, qux)에 대한 고유 제한 조건을 넣을 수 있습니다. no_data_found는 자 동 트랜잭션을 실행하여 삽입을 시도하고 제약 조건 핸들러 + 루프 (고정 재 시도 횟수)를 사용하여 충돌을 처리합니다. –

+0

장기 실행 트랜잭션은 필자가 사용 해본 RDBMS에서는 확실한 no-no입니다. –

답변

1

AUTONOMOUS_TRANSACTION pragma로 정의 된 PL/SQL 함수에 MERGE 및 SELECT 문을 캡슐화 할 수 있습니다.

다른 세션이 방금 동일한 UUID를 삽입했기 때문에 고유 제한 조건 위반이 발생하면 함수에서 예외를 catch하고 UUID를 선택하여 반환 할 수 있습니다.

이 방법을 사용하면 MERGE 문은 짧은 기간 (함수가 실행되는 한)에만 레코드를 잠그고 응용 프로그램은 현재 트랜잭션을 유추하지 않습니다. 함수가 별도의 트랜잭션에서 실행되고 수행하기 때문입니다 유일한 제약 조건 위반의 경우 오류 처리

2

트랜잭션이 커밋 된 후에 만 ​​삽입이 표시되기 때문에 장기 실행 트랜잭션을 수행 할 수 없습니다.

응용 프로그램 계층에서 새 트랜잭션을 연 다음 MERGE 또는 UPSERT로 열려야합니다. 이렇게하면 MERGE/UPSERT 원 자성이 사용자가 발행 한 2 차 트랜잭션에 의해 보장됩니다. 이렇게하면 보조 트랜잭션이 커밋 된 후 READ_COMMITTED에서는 실행되지만 SERIALIZABLE에서는 실행되지 않는 경우 장기 실행 트랜잭션이 변경 내용을 볼 수 있습니다.

비슷한 접근법은 Hibernate, TABLE 기반 식별자로 취해진 다. this article에서 자세한 내용을 볼 수 있습니다.

+0

이 테스트하고 병렬로 트랜잭션을 실행하여 가장 잘 작동합니다. 결국, 나는 원시 데이터 테이블에 데이터를 소비하고 잠재적 인 충돌없이 uuids를 할당하는 전용의 단일 작업자를 갖는 것이 훨씬 더 빠른 옵션이라는 것을 알게되었습니다. –