오랜만에 블로그를 작성한다!
현재 취업준비로 상당히 바쁜상황이다..
cs공부하랴 알고리즘 공부하랴 프로젝트하랴 자소서 쓰랴....
그러던 와중에 프로젝트에서 트랜잭션의 Isolation Level에 따른 트랜잭션 처리를 했던 경험이 있어서 이를 블로그에 남기려 한다.
- 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것.
- 한 트랜잭션이 다른 트랜잭션이 변경한 데이터에 대한
접근 강도
- 레벨이 높아질수록 트랜잭션간 고립정도가 높아지며, 성능저하도 야기된다.
- 일반적인 서비스에선
READ COMMITTED
나REPEATABLE READ
중 하나를 사용한다.
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
트랜잭션의
ACID 특성
을 보장하기 위해서 사용한다.
ACID 모두 다 지키려고 노력하다보면 동시성에 대한 성능이 저하된다.
따라서, 트랜잭션 격리 수준을 나누어 ACID 특성을 너무 타이트하게 지키지 않게끔 만들어준다.
무조건적인 Locking은 데이터베이스의 성능은 떨어지게 된다.
각 격리 수준에 대해서 알아보기 전에 먼저 동시성 부작용 종류들을 알아보겠다.
1.Dirty Read
- 아직
커밋되지 않은
다른 트랜잭션의 데이터를 읽는 것
Non-repeatable Read
- 다른 트랜잭션이 커밋한 데이터를 읽을 수 있는 것
- 즉, 한 트랜잭션에서 같은 쿼리로 2번이상 조회했을 때 기존 데이터가 변경된 상황
Phantom Read
- 한 트랜잭션에서 같은 쿼리로 2번이상 조회했을 때 없던 결과가 조회되는 상황
- 데이터를 추가하거나 삭제할 때 발생
어떤 트랜잭션의 내용이
커밋이나 롤백과 상관없이
다른 트랜잭션에서 조회 가능
정합성의 문제가 많은 격리 수준이기 때문에 RDBMS 표준에서는 격리수준으로 인정X
Select문이 실행되는 동안 해당 Data에 Shared Lock이 걸리지 않는다.
이런 이유로Dirty Read
가 발생하게 된다.
한 트랜잭션의 변경내용이 커밋되어야만 다른 트랜잭션에서 조회 가능
대부분의 RDBMS에서 Default 값
Select문이 실행되는 동안 Shared Lock이 걸린다.
조회시에는 실제 테이블 값이 아니라 Undo 영역에 백업된 레코드 값을 가져온다.
하지만, 하나의 트랜잭션에서 똑같은 SELECT쿼리를 실행했을 때는 항상 같은 결과를 가져와야하는REPEATABLE READ
의 정합성에 어긋난다.
즉,Non-repeatable Read
가 발생한다.
트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회 가능
MySQL의 Default 값
트랜잭션이 완료될 때까지 Select문이 사용하는 모든 데이터에 Shared Lock이 걸린다.
따라서, 트랜잭션이 범위 내에서 조회한 데이터의 내용이 항상 동일함을 보장한다.
트랜잭션 도중에 다른 트랜잭션이 새로운 레코드를 추가하거나 삭제하는 것을 방지하지 못하기 때문이다.
이로인해Phantom Read
가 발생하게 된다.
가장 단순하면서 엄격한 격리 수준이지만, 성능 측면에서는 동시 처리성능이 가장 낮다.
트랜잭션들이 동시에 일어나지 않고, 순차적으로 실행되는 것처럼 동작한다.
Isolation Level이 밑으로 내려갈수록 안정성은 보장이 되나, 처리량이 감소한다. 따라서 적절히 타협을 봐서 Isolation Level을 결정해야 한다.
우리가 잘 알고 있는 @Transactional에 추가 설정해주면 된다.
@Transactional(isolation = Isolation.READ_COMMITTED) public int method(int i) throws Exception { return sqlMapClient.delete("~~~~"); }