락(Lock)
- 데이터베이스에서 동시성 제어와 데이터 무결성을 유지하기 위해 사용하는 메커니즘
- 여러 트랙잭션이 동일 데이터에 조작하려고 할 때 충돌을 방지하고 데이터의 일관성을 보장함
- 예를 들어, 은행 계좌 이체 작업에서 계좌 잔액을 수정하는 트랜잭션이 동시에 실행되면 데이터가 불일치할 수 있으므로 락을 사용하여 이를 방지
트랜잭션이란?
데이터베이스에서 하나의 논리적 작업 단위로, 모든 작업이 성공하거나 실패해야 하는 것을 보장함
락의 종류
데이터베이스 락은 접근 권한과 충돌 관리 전략에 따라 분류함
1) 접근 권한에 따른 분류
공유락(Shared Lock, S-Lock)
- 공유락은 데이터를 읽을 때 사용되는 락
- 공유락이 걸린 자원은 다른 트랙잭션들이 읽기 연산(SELECT)만 실행가능 하며, 쓰기 연산(UPDATE, DELETE)은 불가능
- 하나의 데이터를 여러 트랙잭션이 동시에 읽을 수 있음
- 공유락이 걸린 데이터에 대해서 다른 트랙잭션도 공유락을 획득 할 수 있지만, 배타락은 획득 할 수 없음
- 현재 트랙잭션에서 조회한 데이터가 연산을 처리하는 동안 다른 트랙잭션에 의해 변경되지 않음을 보장함
- 예를 들어, 은행의 계좌 잔액 조회 시, 공유락이 걸리면 다른 트랜잭션에서 계좌 잔액을 수정하려는 시도가 차단됨. 하지만 동일 데이터를 읽으려는 다른 트랜잭션은 문제없이 조회 가능
SELECT FOR SHARE, SELECT ... LOCK IN SHARE MODE 를 통해 공유락 설정
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1 LOCK IN SHARE MODE;
START TRANSACTION;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
배타락(Exclusive Lock, X-Lock)
- 배타락은 데이터를 수정 할 때 사용되는 락
- 배타락이 걸린 자원은 다른 트랙잭션들이 공유락 및 쓰기 연산(UPDATE, DELETE) 모두 불가능
- 배타락이 걸린 데이터는 다른 트랙잭션에서 공유락 및 배타락 둘다 획득 불가능
- 하나의 트랙잭션만 해당 데이터에 접근 가능하며, 동시에 다른 트랙잭션이 접근하는 것을 차단
- 예를 들어, 특정 계좌의 잔액을 갱신하는 트랜잭션이 배타락을 획득한 경우, 다른 트랜잭션은 해당 계좌를 읽거나 수정하려는 시도가 모두 차단됨. 이러한 방식으로 데이터 무결성을 보장
SELECT FOR UPDATE 를 통해 배타락 설정
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
2) 충돌 관리 전략에 따른 분류
비관적 락 (Pessimistic Lock)
- 비관적 락은 동시성 문제가 발생할 것이라고 가정하며, 데이터 접근에 대해 항상 락을 거는 방식임
- 하나의 트랙잭션이 데이터를 읽는 시점에서 락을 걸고 조회 및 업데이트가 완료될 때까지 유지함
- 락이 해제 되기 전까지 다른 트래잭션은 대기하므로, 성능이 저하 될 수 있음
- 주로 공유락(S-Lock)과 배타락(X-Lock)을 통해 구현.
- 데드락(Deadlock)을 유발할 수 있으므로 주의해야함
- 충돌 가능성이 높고, 데이터 무결성이 중요하며, 쓰기 작업이 많은 경우에 사용
데드락(Deadlock)이란?
두 개 이상의 트랜잭션이 서로가 필요로 하는 자원을 점유하고, 서로가 자원을 해제하지 않아 작업이 더 이상 진행되지 않는 상태. 교착 상태라고도 함
낙관적 락 (Optimistic Lock)
- 낙관적 락은 비관적 락과는 달리 여러 트랙잭션이 동시에 값을 수정하지 않는다고 가정함
- 또한, 비관적 락과는 달리 데이터베이스가 제공하는 락이 아닌 애플리케이션 레벨에서 락을 구현함
- 낙관적 락은 애플리케이션에서 충돌을 관리하기에 트랜잭션을 커밋하기 전까지는 충돌을 알 수 없다.
- 즉, 자원에 락을 걸지 않고, 충돌이 발생하면 그때 해결하는 방식
- version 등의 구분 컬럼을 이용해서 충돌을 예방
- 충돌 가능성이 낮고, 동시성과 성능이 중요한 경우에 사용
비관적 락은 데이터베이스에 락을 설정하므로, 트랜잭션 대기 시간과 성능 저하가 발생할 수 있음.
반면, 낙관적 락은 충돌 시 재시도 오버헤드가 발생하므로, 상황에 맞게 선택해야 함.