이 페이지에서는 반복 가능한 읽기 격리에서 FOR UPDATE
절을 사용하는 방법을 설명합니다.
FOR UPDATE
절의 잠금 메커니즘은 반복 가능한 읽기와 직렬화 가능한 격리에서 서로 다릅니다. 직렬화 가능 격리와 달리 FOR UPDATE
절은 반복 가능 읽기 격리에서 잠금을 획득하지 않습니다. FOR UPDATE
의 잠금에 대한 자세한 내용은 직렬화 가능한 격리에서 SELECT FOR UPDATE 사용을 참고하세요.
FOR UPDATE
절을 사용하는 방법을 알아보려면 GoogleSQL 및 PostgreSQL
FOR UPDATE
참조 가이드를 참고하세요.
FOR UPDATE
절을 사용하는 이유
트랜잭션이 반복 가능한 읽기 격리로 실행되면 SELECT
문으로 쿼리된 데이터는 항상 트랜잭션에 대해 설정된 스냅샷 타임스탬프에서 반환됩니다. 그런 다음 트랜잭션이 쿼리된 데이터를 기반으로 업데이트를 실행하는 경우 동시 트랜잭션도 쿼리된 데이터를 업데이트하면 정확성 문제가 발생할 수 있습니다. 자세한 내용은 읽기-쓰기 충돌 및 정확성을 참고하세요.
SELECT
문으로 쿼리된 데이터가 트랜잭션이 커밋될 때도 유효하도록 하려면 반복 가능한 읽기 격리와 함께 FOR UPDATE
절을 사용하면 됩니다. FOR UPDATE
를 사용하면 읽기-쓰기 충돌에도 불구하고 트랜잭션 정확성이 보장됩니다. 읽기와 수정 사이에 다른 트랜잭션에 의해 데이터가 수정되었을 수 있습니다.
쿼리 구문
이 섹션에서는 FOR UPDATE
절을 사용할 때의 쿼리 구문을 안내합니다.
가장 일반적인 사용법은 최상위 SELECT
문에 있습니다. 예를 들면 다음과 같습니다.
SELECT SingerId, SingerInfo
FROM Singers WHERE SingerID = 5
FOR UPDATE;
FOR UPDATE
절은 트랜잭션이 커밋될 때 SELECT
문과 SingerID = 5
로 쿼리된 데이터가 여전히 유효하도록 보장하여 동시 트랜잭션이 쿼리된 데이터를 업데이트할 경우 발생할 수 있는 정확성 문제를 방지합니다.
WITH 문에서 사용
WITH
문에 대한 외부 수준 쿼리에서 FOR UPDATE
를 지정하면 FOR UPDATE
절은 WITH
문 내에서 검색된 범위를 확인하지 않습니다.
다음 쿼리에서는 FOR UPDATE
가 공통 테이블 표현식 (CTE) 쿼리로 전파되지 않으므로 스캔된 범위가 검증되지 않습니다.
WITH s AS (SELECT SingerId, SingerInfo FROM Singers WHERE SingerID > 5)
SELECT * FROM s
FOR UPDATE;
CTE 쿼리에 FOR UPDATE
절이 지정되면 CTE 쿼리의 스캔된 범위가 검증됩니다.
다음 예시에서는 SingerId > 5
가 유효성 검사된 행의 SingerId
및 SingerInfo
셀입니다.
WITH s AS
(SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5 FOR UPDATE)
SELECT * FROM s;
서브 쿼리에서 사용
하나 이상의 하위 쿼리가 있는 외부 수준 쿼리에서 FOR UPDATE
절을 사용할 수 있습니다. 최상위 쿼리와 하위 쿼리 내에서 스캔된 범위는 표현식 하위 쿼리를 제외하고 검증됩니다.
다음 쿼리는 SingerId > 5.
에 대해 SingerId
및 SingerInfo
셀을 검증합니다.
(SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5) AS t
FOR UPDATE;
다음 쿼리는 표현식 하위 쿼리 내에 있으므로 Albums
테이블의 셀을 검증하지 않습니다. 표현식 하위 쿼리에서 반환된 행의 SingerId
및 SingerInfo
셀이 검증됩니다.
SELECT SingerId, SingerInfo
FROM Singers
WHERE SingerId = (SELECT SingerId FROM Albums WHERE MarketingBudget > 100000)
FOR UPDATE;
뷰를 쿼리하는 데 사용
다음 예시와 같이 FOR UPDATE
절을 사용하여 뷰를 쿼리할 수 있습니다.
CREATE VIEW SingerBio AS SELECT SingerId, FullName, SingerInfo FROM Singers;
SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;
뷰를 정의할 때 FOR UPDATE
절을 사용할 수 없습니다.
지원되지 않는 사용 사례
다음 FOR UPDATE
사용 사례는 지원되지 않습니다.
- Spanner 외부에서 코드를 실행하기 위한 상호 제외 메커니즘: Spanner 외부 리소스에 대한 독점 액세스를 보장하는 데 Spanner의 잠금을 사용하지 마세요. Spanner에 의해 트랜잭션이 중단될 수 있습니다. 예를 들어 애플리케이션 코드에서 명시적으로 또는 Spanner JDBC 드라이버와 같은 클라이언트 코드에서 암시적으로 트랜잭션이 재시도되는 경우 커밋된 시도 중에만 잠금이 보장됩니다.
LOCK_SCANNED_RANGES
힌트와 함께 사용: 동일한 쿼리에서FOR UPDATE
절과LOCK_SCANNED_RANGES
힌트를 모두 사용할 수는 없으며, 그러지 않으면 Spanner에서 오류를 반환합니다. 자세한 내용은LOCK_SCANNED_RANGES
힌트와의 비교를 참고하세요.- 전체 텍스트 검색 쿼리: 전체 텍스트 검색 색인을 사용하는 쿼리에서는
FOR UPDATE
절을 사용할 수 없습니다. - 읽기 전용 트랜잭션:
FOR UPDATE
절은 읽기-쓰기 트랜잭션 내에서 실행되는 쿼리에서만 유효합니다. - DDL 문 내: 나중에 실행하기 위해 저장된 DDL 문 내의 쿼리에서는
FOR UPDATE
절을 사용할 수 없습니다. 예를 들어 뷰를 정의할 때FOR UPDATE
절을 사용할 수 없습니다.
다음 단계
- GoogleSQL 및 PostgreSQL에서
FOR UPDATE
절을 사용하는 방법 알아보기 - 직렬화 가능한 격리에서 SELECT FOR UPDATE 사용 방법을 알아보세요.
LOCK_SCANNED_RANGES
힌트에 대해 알아보기- Spanner의 잠금에 대해 알아보기