동시성 제어를 위해 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;

 

+ Recent posts