복붙노트

[SPRING] 거래로 상향 조정

SPRING

거래로 상향 조정

PostgreSQL과 함께 Spring을 사용하고 있으며 다음과 같은 코드를 사용하여 일종의 UPSERT를 시도합니다.

jt.update("delete from A where id = 1")
jt.update("insert into A (id, value) values (1, 100)")

@Transactional을 사용하여) 트랜잭션 내부를 래핑합니다.

문제는 많은 동시 요청이있을 때이 코드가 '중복 키'오류로 실패하여 트랜잭션이 격리되지 않았거나 ...

거래 방법에 관한 정보가 누락 되었습니까? 여기에 다른 메커니즘을 사용해야합니까 (예 : 스레드 동기화)?

해결법

  1. ==============================

    1.나는 그것에 대해 다소 큰 blogpost를 썼다. 그래서 링크를위한 downvotes를 얻을지도 모르지만, 이것을 읽는다.

    나는 그것에 대해 다소 큰 blogpost를 썼다. 그래서 링크를위한 downvotes를 얻을지도 모르지만, 이것을 읽는다.

    요점은 트랜잭션이 여기에서 도움이되지 않는다는 것입니다 (적어도 기본적으로). 올바른 upsert를 작성할 수는 있지만 실제로는 꽤 까다 롭습니다.

  2. ==============================

    2.이 간단한 테이블을 가정하면 다음과 같습니다.

    이 간단한 테이블을 가정하면 다음과 같습니다.

    CREATE TABLE tbl(id int primary key, value int);
    

    이 기능은 동시 트랜잭션에 대해 거의 100 % 안전합니다 (주석 참조).

    CREATE OR REPLACE FUNCTION f_upsert(_id int, _value int)
      RETURNS void AS
    $func$
    BEGIN
    LOOP
       UPDATE tbl SET value = _value WHERE  id = _id;
    
       EXIT WHEN FOUND;
    
       BEGIN
          INSERT INTO tbl (id, value)
          VALUES (_id, _value);
    
          RETURN;
    
       EXCEPTION WHEN UNIQUE_VIOLATION THEN     -- tbl.id has UNIQUE constraint.
          RAISE NOTICE 'It actually happened!'; -- hardly ever happens
       END;
    
    END LOOP;
    END
    $func$ LANGUAGE plpgsql;
    

    요구:

    SELECT f_upsert(2, 2);
    

    이것은 INSERT / SELECT 케이스와 매우 유사합니다. 자세한 설명과 링크가 있습니다 :

  3. from https://stackoverflow.com/questions/17152860/upsert-with-a-transaction by cc-by-sa and MIT license