과거의 데이터베이스는 동시성을 제어하기 위해 강력한 락(Lock)을 사용했습니다.
하지만 이렇게 하면 대기 시간이 길어져 성능이 떨어집니다. 이를 해결하기 위해 나온 것이 MVCC입니다.
"데이터를 덮어쓰지 말고, 새로운 버전을 하나 더 만들자!"
즉, 데이터에 변경이 일어날 때 기존 데이터를 지우는 것이 아니라 새로운 버전(Snapshot)을 생성하여 관리합니다.
MVCC 모델에서 가장 중요한 원칙은 "읽기 작업(Reader)은 쓰기 작업(Writer)을 방해하지 않고, 쓰기 작업도 읽기 작업을 방해하지 않는다"는 것입니다.
상황: ID=1인 유저의 나이가 20살입니다.
트랜잭션 A (읽기): 오후 1시에 조회를 시작합니다. (이때 나이는 20살)
트랜잭션 B (쓰기): 오후 1시 1분에 나이를 21살로 UPDATE 하고 아직 커밋(Commit)은 안 했습니다.
트랜잭션 A (다시 읽기): 오후 1시 2분에 다시 조회를 합니다.
MVCC라고 해서 락을 아예 안 쓰는 것은 아닙니다. "읽기에는 락을 안 쓰고, 쓰기에는 락을 쓴다"가 정확합니다.
| 구분 | 설명 | 락 사용 여부 |
|---|---|---|
| 일반 읽기 | (Consistent Read),SELECT * FROM ... | Lock 없음 (X) 특정 시점의 스냅샷(버전)을 읽음. 가장 빠름. |
| 잠금 읽기 | (Locking Read),SELECT ... FOR UPDATE | Lock 사용 (O) 데이터를 수정할 의도로 읽는 것이므로 최신 버전을 읽고 락을 걺. |
| 쓰기 | (Write),"INSERT, UPDATE, DELETE" | Lock 사용 (O) 데이터 정합성을 위해 해당 행(Row)에 락을 걺. |