낙관적 락과 비관적 락
낙관적 락과 비관적 락은 데이터베이스 트랜잭션에서 동시성 제어를 위한 주요 기법입니다. 데이터 무결성을 유지하면서 여러 트랜잭션이 동시에 데이터에 접근할 때 발생할 수 있는 충돌을 해결할 때 사용됩니다.
✔️ 낙관적 락 (Optimistic Lock)
데이터 충돌이 적을 것으로 가정하고, 데이터를 읽을 때 락을 설정하지 않고 트랜잭션이 데이터를 수정할 때 충돌이 발생하지 않았는지 확인하는 방식입니다. 보통 version
과 같은 별도의 구분 컬럼을 사용해서 데이터가 변경되었는지 확인하며, 충돌이 발생하면 데이터베이스가 아닌 애플리케이션에서 직접 롤백하거나 재시도 처리를 해야 합니다.
✔️ 비관적 락 (Pessimistic Lock)
데이터 충돌이 많을 것으로 가정하고, 트랜잭션이 시작될 때 공유락(Shared Lock, S-Lock)
또는 베타락(Exclusive Lock, X-Lock)
을 설정하여 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 하는 방식입니다.
S-Lock: 다른 트랜잭션에서 읽기는 가능하지만 쓰기는 불가능합니다.
X-Lock: 다른 트랜잭션에서 읽기, 쓰기 모두 불가능합니다.cf. MySQL은
일관된 읽기(Consistent Nonlocking Reads)
를 지원하여X-Lock
이 걸려 있어도 단순SELECT
로 읽을 수 있습니다.
MySQL에서는 단순 SELECT 문이 락이 걸린 row에 대해서 블로킹되지 않습니다. (InnoDB 엔진 기준, 기본 설정 기준)
MySQL의 InnoDB
스토리지 엔진은 MVCC(Multi-Version Concurrency Control)를 사용합니다.
즉, SELECT
는 락을 걸지 않고, 트랜잭션 격리 수준에 따라 스냅샷된 데이터 버전을 읽습니다.
따라서 누군가 UPDATE
나 DELETE
로 특정 row에 쓰기 락을 잡고 있어도, SELECT * FROM table WHERE id = 1;
같은 단순 조회는 락을 기다리지 않고 바로 실행됩니다.
✔️ 두 방식의 차이점은 뭘까?
낙관적 락
은 충돌이 발생하면 해결하는 방식이고, 비관적 락
은 애초에 충돌을 방지하는 방식입니다.
데이터 충돌이 자주 발생하거나 데이터 무결성이 중요한 경우에는 비관적 락
을 사용하는 것이 유리할 수 있습니다.
조회 작업이 많고 동시 접근 성능이 중요한 경우에는 낙관적 락
을 사용하는 것이 유리할 수 있습니다.
충돌 가능성
낙관적 락
은 충돌이 자주 발생하지 않을 것이라고 가정하고, 비관적 락
은 충돌이 자주 발생할 것이라고 가정합니다.
데이터베이스 락 사용 여부
낙관적 락
은 락을 사용하지 않고, 비관적 락
은 트랜잭션이 시작될 때 락을 설정합니다.
성능
낙관적 락
은 락을 설정하지 않기 때문에 성능이 더 좋을 수 있습니다. 하지만 충돌이 발생할 경우 롤백하거나 재시도 처리를 해야 하기 때문에 성능이 떨어질 수 있습니다.
비관적 락
은 락을 설정하기 때문에 다른 트랜잭션이 대기해야 하며, 이로 인해 성능이 저하될 수 있습니다.