저번 시간에 동시성 제어의 배경과 하지 않았을 때의 문제점을 살펴보았다.
이번에는 동시성 제어 기법의 종류를 설명하고자 한다.
동시성 제어에는 Lock을 사용한 방법이 있다. 이번 시간에는 낙관적 락과 비관적 락에 대해서 알아본다.
충돌하지 않을 것이라고 보고 진행한다.
그렇다면 어떻게 충돌을 방지할까?
버전(Version)을 사용한다. 해당 데이터의 버전을 읽고, 데이터를 Commit하기 전에도 다시 버전을 읽는다.
이 두 버전이 일치할 때 비로소 Commit을 한다.
대략적 이미지는 아래와 같다.
이렇게 하면, 누군가가 동시에 데이터를 수정했을 때 먼저 수정한 사람의 Commit으로 인해 버전이 변경된다. 따라서 두 번째로 데이터를 수정하려는 사람은 처음 읽었을 때의 버전과 Commit 전에 읽은 버전이 달라진 것을 확인하고, 충돌이 발생할 뻔했다는 것을 인지하게 되어 롤백을 한다.
충돌할 걸 예상하고 락을 걸어서 진행하는 방식이다.
락을 걸고 데이터를 수정하는 동안, 다른 사용자는 자원을 이용할 수 없기에 대기를해야 한다.
여기에는 배타락(Exclusive lock)과 공유락(Shared lock)이 있다.
흔하게 생각해 볼 수 있는 방식으로, 한 트랜잭션이 진행되는동안 다른 트랜잭션이 접근을 못하게 Lock을 걸어둔다.
이는 전용 lock이라고도 하며, Lock이 걸리는 순간 다른 트랜잭션의 읽기와 쓰기는 불가능하다. Commit이 끝난 뒤 Lock이 풀리면 다음 트랜잭션이 권한을 가져간다.
read연산은 가능하고 write연산은 불가능 하게 끔 한다.
한 트랜잭션이 공유 락을 걸면 다른 트랜잭션도 동일한 데이터에 공유 락을 걸 수 있지만, 배타 락은 걸 수 없다.
우리가 여기서 알아야 할 점은 로킹 단위(Loking Granularity)이다.
즉 어떤 범위로 묶어서 Lock을 걸 것이냐 ? 라는 의미인데
크다 --------------------------------> 작다
데이터베이스, 릴레이션, 튜플, 속성 단위로 가능하다.
로킹 단위가 커질수록 구현이 쉽고 (그냥 대충 한번에 묶어버리면 되니깐_)
병행성 수준이 낮아진다. 때문에 로킹 오버헤드 감소
로킹 단위가 작아지면 병행성 수준이 높아져 여러 트랜잭션이 동시에 진행될 수 있지만, 관리가 어렵고 락 오버헤드가 증가
이렇게 종류를 알아보았다.
그렇다면 언제 낙관을 쓰고 언제 비관을 쓰는가?
👋다음 시간에는 이로 인해 발생하는 데드락이 무엇인지 알아본다.👋