트랜잭션(Transaction): 일이 처리되는 가장 작은 단위
DB 격리 수준
Read commit
- A의 트랜잭션 시작 이후 Update 문(임꺽정 → 장보고)을 수행했을 때 기존 데이터(임꺽정)를 Undo 영역에 저장하고 관리한다.
- B가 Select 문을 수행했을 때 Undo 영역의 데이터(임꺽정)를 읽는다.
- A가 Commit(트랜잭션 종료) 했을 때, Undo 영역의 데이터가 변경된 데이터(장보고)로 변경된다.
문제점
위와 같은 경우에는 B가 트랜잭션을 시작하지않고 Select문만 실행하기 때문에 문제가 없다.
하지만
A와 정산이라는 프로그램이 트랜잭션을 시작하고 A가 데이터를 Update 한 이후 커밋을 진행한다.
이러한 문제는 주로 입금, 출금 처리가 진행되는 금전적인 처리에서 주로 발생하며, 데이터의 정합성은 깨지고, 버그는 찾기 어려워 진다. PHANTOM READ
현상도 발생한다.
이후 정산의 트랜잭션이 종료되지 않은 상황에 다시 데이터를 읽으면 값이 변경됨을 알 수 있다.
이는 하나의 트랜잭션내에서 똑같은 SELECT 쿼리를 실행했을 때는 항상 같은 결과를 가져와야 하는 REPEATABLE READ
의 정합성에 어긋난다(부정합).
해당 문제를 해결하기 위해서는 Repeatable Read
를 사용해야 한다.
Repeatable Read
- MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다. (본인의 트랜잭션 종료 전에 커밋된 트랜잭션의 영향을 받지 않음)
- Update 쿼리에는 정합성을 보장하지만 Insert 쿼리에는 정합성을 보장하지 못한다.
- Undo 공간에 백업해두고 실제 레코드 값을 변경한다.
- 백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제한다.
- Undo에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있다.
- 이러한 변경방식은 MVCC(Multi Version Concurrency Control)라고 부른다.
참고