동시성 제어를 위해 select ... left join ... for update를 사용하여 배타 락을 획득할 때 다음과 같은 에러를 만났습니다.
"FOR UPDATE cannot be applied to the nullable side of an outer join"
실행하려 했던 SQL은 대략 아래와 같습니다.
SELECT *
FROM member
LEFT JOIN team
ON member.team_id = team.team_id
FOR UPDATE;
한 트랜잭션A에서 위 SQL이 실행될 때 team이 조인이 되지 않아서 null 상태로 읽었다고 가정해 보겠습니다.
결과 셋은 아래와 같습니다.
이 트랜잭션이 커밋되기 전에 다른 트랜잭션 B로부터 team_id : 1이 삽입되었다면, team_id 1은 락에 걸려야 할지 안걸려야 할 지 모호합니다. 이러한 일관성의 문제 등의 이유로 left join을 비롯한 outer join 은 for update 가 불가합니다.
해결방법은 2가지가 있습니다.
1. inner join
조인이 수행된 team 테이블의 레코드라도 잠그고 싶다면, inner join을 통해 해결할 수 있습니다.
SELECT *
FROM member
INNER JOIN team
ON member.team_id = team.team_id
FOR UPDATE;
2. for update of 테이블명
outer join 된 결과 셋이 더 중요하다면 of 옵션으로 명시된 테이블의 락만 획득할 수 있습니다.
이 경우 team 레코드가 조인되었어도 잠그지 않습니다.
물론 postgres REAPEATABLE READ 이상의 격리 수준에서는 NON_REPEATABLE READ 나 팬텀 리드 현상이 없기 때문에 트랜잭션 내에서 team 관련 결과 셋이 바뀔 일은 없습니다.
SELECT *
FROM member
LEFT JOIN team
ON member.team_id = team.team_id
FOR UPDATE OF member;
'경험과 지식' 카테고리의 다른 글
NestJS passport 인증 딥다이브 (0) | 2025.02.21 |
---|---|
제네릭, 와일드카드 처음부터 끝까지 이해하기[with PECS, <E extends Comparable<? super E>> E max(Collection<? extends E> c)] (0) | 2023.12.27 |
트랜잭션 격리수준 4단계 테스트(mysql innoDB) (2) | 2023.12.10 |
JPA N+1문제와 해결방안(2) (0) | 2023.04.10 |
JPA N+1문제와 해결방안(1) (0) | 2022.03.25 |