[DB] 락
DB 락
여러 커넥션들이 동시에 동일 자원에 대한 요청 중 하나의 커넥션만 작업을 할 수 있게 해주는 것 (동시성 제어)
* 락이 왜 필요한가?
예를 들어:
- 계좌 A 잔액이 10,000원 있음
- 동시에 두 사람이 5000원 출금 요청을 보냄
만약 락이 없다면
커넥션1: 10000 조회 → 5000 감소 → 5000 저장
커넥션2: 10000 조회 → 5000 감소 → 5000 저장
결과: 잔액 5000원 → -5000원 사라짐 (데이터 오염 발생)
이렇게 커넥션이 순서를 지키지 않고 뒤엉켜서 작업을 하여
기대랑 다른 예상치 못한 값이 나오는 것을 "Race Condition(경쟁상태)" 라고 한다.
락의 종류
- 공유 락 ( Shared Lock, Read Lock, S-Lock )
데이터를 변경하지 않은 select 작업을 위해 잠그는 것을 말한다.
어느 한 세션에서 select 작업을 하고 있어도 다른 세션이 붙어서 같이 조회한다고 정합성이 깨지지않는다 => 아무런 조취 없음
근데 읽기 작업 수행중, 다른 세션에서 쓰기작업을 수행한다면 기존 세션의 결과가 달라질 수 있음 => 일관된 읽기가 깨지므로
다른 세션의 베타 락 획득을 막는다.
* 공유Lock 획득은 막지 않지만, 어떠한 커넥션도 해당 데이터의 베타 락을 획득하고 수정할 수 없다.
- 베타 락 ( Exclusive Lock, Write Lock, X-Lock )
데이터를 변경하기 위해 잠가서 아무도 접근하지 못하게 막는것
베타락은 데이터를 추가/수정을 하기 때문에 결과가 달라 질 수 있음
그렇기에 공유LOCK 또한 막고 기존의 쓰기 작업에 대한 정합을 위해 베타 락 획득도 막는다.
이러한 락에 의해 Lock 끼리의 경합이 발생하여 특정 트랜잭션 (락도 하나의 트랜잭션 안에서 걸리고 해제됨)
이 작업을 진행하지 못하고 기다리는 상태인 블로킹이 발생하게 된다.
* select * from exam for update : 기본적으로 조회이지만 조회된 모든 행에 대하여 배타적 잠금을 수행하게 된다.
실제로 락이 어떻게 동작하는지 예시
Transaction A
BEGIN
SELECT * FROM account WHERE id=1 FOR UPDATE;
UPDATE account SET balance = balance - 5000 WHERE id=1;
Transaction B
BEGIN
SELECT * FROM account WHERE id=1 FOR UPDATE;
→ A가 락 잡고 있어서 대기 상태
A가 COMMIT하면:
B가 락 획득 → 실행
- 데드 락
두 트랜잭션 모두가 블로킹 상태에 진입하여 서로가 서로의 자원을 원하면서 기다리는 상태
or
두 개이상의 트랜잭션이 서로가 가진 자원을 기다리면서 아무도 앞으로 나아가지 못하고 물린 상태

* 대부분의 RDBMS는 데드락을 자동감지하고, 둘 중 한 트랜잭션을 강제로 죽여서 해결한다.
데이터 무결성
- 데이터가 정확하고, 완전하며 신뢰할 수 있는 상태를 유지하는 것
- 데이터가 정의된 구조적, 논리적 규칙(제약 조건)을 잘 준수했는지를 보장하는 데 초점을 맞춥니다.
- 즉, 데이터 자체의 **품질(Quality)**과 **신뢰성(Reliability)**에 관한 문제입니다.
- 개체 무결성 : 모든 테이블은 기본키를 가져야 하며, 기본키는 NULL이 아니여야 한다.
-참조 무결성 : 외래키는 참조하는 테이블의 기본키 값과 일치하거나 NULL 이어야 한다.
- 도메인 무결성 : 특정 속성에 저장될 수 있는 값의 유형, 길이, 범위 등이 정의된 규칙에 맞아야 한다.
(ex: Age 필드는 양수만, Gender 필드는 남자는 1 여자는 0)
- 업무 무결성 : 특정 비지니스 로직에 따른 규칙을 만족하도록 보장해야 한다.
(계좌 잔고가 음수가 되지 않도록 하는 규칙)
데이터 정합성
- 서로 관련된 데이터들이 모순없이 일관되게 일치하는 상태
ex : 재고가 감소해야하는데 실제 재고관리에서 반영되지 않는것,
한 고객의 주소 정보가 여러 테이블에 저장되어 있을때, 한 테이블에서만 주소가 수정되고 나머지는 그대로 남아 있는것.
블로킹 상태시 해결방안
블로킹 상태가 길어지면 서비스에 작업들이 모두 지연되기 때문에 해결방법이 중요하다.
* 트랜잭션 작업 단위를 최대한 적게 가져가기
작업수행을 짧고 가볍게 할 수록 더 빨리 끝나기 때문에 락 지속시간도 짧아진다.
* 동일한 데이터를 동시에 변경하는 작업을 하지 않도록 설계 (동시성을 위한 비관적 락, 낙관적 락 사용)
* 트랜잭션이 활발한 주간에는 대용량 데이터 작업을 지양하기