나는 전에 MySQL에서와 같은 동시성 문제에 대해 들었다. Postgres에서는 그렇지 않습니다.
기본 READ COMMITTED
트랜잭션 격리 수준 의 기본 제공 행 수준 잠금 이면 충분합니다.
한 테이블에서 다른 테이블로 직접 값을 전달하는 것이 편리하기 때문에 데이터 수정 CTE (MySQL에도없는 것)가있는 단일 명령문을 제안합니다. 당신은 아무것도 필요하지 않으면 coupon
테이블에 별도의와 트랜잭션을 사용할 수 있습니다 UPDATE
및 INSERT
단지뿐만 아니라 문.
WITH upd AS (
UPDATE coupon
SET used = true
WHERE coupon_id = 123
AND NOT used
RETURNING coupon_id, other_column
)
INSERT INTO log (coupon_id, other_column)
SELECT coupon_id, other_column FROM upd;
하나 이상의 거래에서 동일한 쿠폰을 사용하려고 시도하는 경우 는 드 rare니다 . 그들은 고유 번호를 가지고 있지 않습니까? 같은 순간에 여러 번 시도하는 트랜잭션은 훨씬 드 물어야합니다. (아마도 응용 프로그램 버그이거나 누군가 게임을하려고합니까?)
그것이 무엇이든간에, UPDATE
유일한 것은 하나의 거래에 대해서만 성공합니다 . 는 UPDATE
취득 로우 레벨 잠금 업데이트하기 전에 각각의 타겟 행에있다. 동시 트랜잭션 UPDATE
이 동일한 행을 시도하면 행에 잠금이 표시되고 블로킹 트랜잭션이 완료 될 때까지 기다린 후 ( ROLLBACK
또는 COMMIT
) 잠금 큐에서 첫 번째가됩니다.
경쟁 조건에 대한 가능성 은 없습니다 .
동일한 트랜잭션에 더 많은 쓰기를 넣거나 다른 것보다 더 많은 행을 잠그지 않으면 교착 상태 가 발생할 가능성 이 없습니다 .
는 INSERT
관리-무료입니다. 실수로 coupon_id
이미 log
테이블에 있고 UNIQUE 또는 PK 제약 조건 log.coupon_id
이있는 경우 고유 한 위반 후 전체 트랜잭션이 롤백됩니다. DB에 잘못된 상태를 나타냅니다. 위의 명령문이 log
테이블 에 쓸 수있는 유일한 방법 인 경우 절대로 발생하지 않아야합니다.