1. 데이터베이스에 잠금이 왜 필요할까? - 동시성 제어
위와같이 민트초코가 1개 남았고 동시에 접근을 한다고 가정한다. 동시에 접근을 한 두 명의 사용자는 재고 수량을 읽는다. 한 명의 사용자가 구매를 완료하고 재고를 업데이트 한다. 뒤늦게 다른 사용자가 구매를 완료하고 다시 재고를 업데이트시킨다. 업데이트를 아까 시켜줬는데 그 위에 덮어쓰기가 되었다. 남은 수량은 1개 였는데 두 사람 모두 주문이 완료된 상황이 발생하게 된것이다. 커머스 서비스에서 이러한 일이 일어난다면 치명적일 수 있다. 이런한 문제를 해결하기 위해서 동시성 제어가 필요하다.
- 동시성 제어 : 트랜잭션들이 동시에 수행될 때, 일관성을 해치지 않도록 접근을 제어하는 DBMS의 기능
동시성 제어는 어떻게 할까?
바로 Lock을 이용한다. Lock에는 크게 낙관적 잠금과 비관적 잠금이 있다.
2. Lock의 종류 - 낙관적, 비관적
1) Optimisstic Lock 낙관적 잠금
- 데이터 갱신 시 경합이 발생하지 않을 것이라고 봄
- 한 사용자가 업데이트를 완료하면, 동시 업데이트 확약을 시도하는 다른 사용자들에게 충돌이 있음을 알림
먼저 버전을 읽어 와서 일련의 과정을 거치고 구매를 완료한 후 데이터를 업데이트 시켜주기 전 버전을 다시 읽어온다. 처음에 읽어온 버전과 그 다음에 읽어온 버전이 똑같다면 버전을 업데이트 시켜줄 수 있다.
반면 다른 사용자는 구매를 뒤늦게 완료하고 버전을 다시 읽어 오지만 이미 버전이 업데이트 됐기 때문에 처음에 읽었던 버전과 나중에 읽은 버전이 달라 충돌이 발생했음을 알 수 있다. 이후에 롤백을 시켜준다.
2) Pessimistic Lock 비관적 잠금
- 동일한 데이터를 동시에 수정 할 가능성이 높다라고 봄- 다른 사용자는 먼저 시도한 사용자가 변경을 확약해서 레코드 잠금을 릴리스할 때 까지 대기해야 함
데이터에 접근하기 전 Lock을 걸어 주고 일련의 과정들을 거치고 Unlock을 시켜준다. Lock이 걸리고 Unlock이 되는 동안 다른 사용자는 무조건 대기해야 한다.
언제 사용하는 것이 좋을까?
Optimisstic Lock 낙관적 잠금 | Pessimistic Lock 비관적 잠금 |
동시 업데이트가 거의 없는 경우 (롤백을 할 가능성이 많고 빈번하게 일어할 수 있기 때문) |
동시 업데이트가 빈번한 경우 외부 시스템과 연동한 경우 |
3. Pessimistic Lock Lock 연산의 종류 - 공유, 베타
1) 공용(shared) lock
- read 연산 실행 가능, write 연산 실행 불능
- 데이터에 대한 사용권을 여러 트랜잭션이 함께 가질 수 있음
공용락은 먼저 Read 연산은 실행 가능하지만 Write 연산은 실행이 불가능한다. Read 연산은 데이터에 대해서 어떠한 영향도 미칠 수 없기 때문에 여러 트랜잭션이 함께 사용권을 가질 수 있다.
2) 베타(exclusive) lock
- read 연산과 write 연산을 모두 실행 가능
- 베타 lock 연산을 실행한 트랜잭션만 해당 데이터에 대한 독점권을 가짐
베타락은 Read 연산과 Write 연산을 모두 실행가능하다. Write 연산은 데이터를 업데이트 시켜줄 가능성이 있기 때문에
해당 데이터에 대한 독점권을 가진다.
Lock 연산의 양립성
공용 lock (read) |
베타 lock (read, write) |
|
공용 lock (read) |
가능 | 불가능 |
베타 lock (read, write) |
불가능 | 불가능 |
공용 Lock은 Read는 가능하기 때문에 양립이 가능하지만 베타 Lock은 Write를 할 가능성이 있어 베타 Lock이 들어가는 순간 양립이 불가능하게 된다.
4. Lock의 단위
Lock의 단위는 크게는 데이터베이스부터 작게는 필드까지 있다. 단위를 크게 가져간다면 구현이 단순하지만 병행성이 떨어진다는 단점이 있고 단위를 작게 가져간다면 구현이 복잡하지만 병행성이 높아지는 장점이 있다.
(락의 단위는 데이터베이스 종류마다 다르기 때문에 참고)
LOCK을 큰 단위로 하나 걸거나 작은 단위로 여기저기 걸어버리면 안되나요?
5. Lock으로 발생할 수 있는 문제점 - 블로킹, 데드락
1) Blocking
- Lock들의 경합이 발생하여 특정 세션이 작업을 진행하지 못하고 멈춰 선상태
why?
- 데이터에 대해서 하나의 트랜잭션이 베타 lock을 걸면 다른 트랜잭선들은 어떠한 lock도 걸지 못하고 대기해야하기 때문
블로킹이 풀리는 시점은?
- 트랜잭션이 commit 혹은 rollback을할 때
Blocking 해결 방안
1. 트랜잭션을 짧게 정의
2. 같은 데이터를 갱신하는 트랜잭션이 동시에 수행되지 않도록 설계
3. LOCK TIMEOUT을 이용하여 잠금해제 시간을 조절
2) DeadLock 교착상태
트랜잭션1이 리소스1에 대해서 베타 Lock을 걸고 트랜잭션2가 리소스2에게 공유 Lock을 걸었다. 이어서 트랜잭션2가 리소스1에게 공유 Lock을 걸어야 하는데 이미 베타 Lock이 걸려있다. 그렇다면 대기를 할 수밖에 없게된다. 마지막으로 트랜잭션1이 리소스2에게 베타 Lock을 걸려고 하는데 공유 Lock이 걸려 있어서 대기해야 한다. 트랜잭션이 서로가 서로를 기다리는 상황이 되는데 이렇게 된다면 무한 대기를 하게 된다.
DeadLock 해결방안
1. 트랜잭션 진행방향을 같은방향으로 처리
2. 트랜잭션 처리속도를 최소화
3. LOCK TIMEOUT을 이용하여 잠금해제 시간을 조절
참고
https://www.youtube.com/watch?v=ZXV6ZqMyJLg&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC
'개발 관련 강의 정리 > 10분 테코톡' 카테고리의 다른 글
[10분 테코톡] 케로의 예외처리 정리 (0) | 2023.06.02 |
---|---|
[10분 테코톡] 마코의 JCF 정리 (0) | 2023.06.01 |
[10분 테코톡] 애쉬의 AWS 살짝 알은체 하기 정리 (0) | 2023.05.29 |
[10분 테코톡] 릭의 MySQL 아키텍처 정리 (0) | 2023.05.28 |
[10분 테코톡] 에덴의 서버 네트워크 정리 (0) | 2023.05.26 |
댓글