본문 바로가기

mysql

non-repeatable read 와 phantom read의 차이점

사실상 non-repeatable read 의 일종이 phantom read 라고 생각하긴한다

그래도 이름이 같지않으니 둘 간의 늬앙스 차이가 있는데

 

non-repeatable read는 좀 더 한 row의 업데이트시 변경점이라는 느낌이다

즉 name,age가 고길동,30이라는 row가 있으면

트랙잭션1 시작

트랜잭션2 시작

트랜잭션1 select // 고길동,30

트랜잭션2 select // 고길동,30

트랜잭션1 update //고길동,31

트랜잭션2 select // 고길동 30

트랜잭션1 커밋

트랜잭션2 select //고길동 31 //위에서는 고길동,30이었는데 같은 트랜잭션안에서 값이 바뀜

트랜잭션2 커밋

 

이런식으로 한 row를 가지고 조회를 하는데 다른트랜잭션의 update에 영향을 받는걸 말하는 느낌이고

 

phantom read는 여러 row를 범위조회할때,갯수의 변경이라는 느낌이다

name,age가 고길동,30이라는 row가 있으면

트랙잭션1 시작

트랜잭션2 시작

트랜잭션1 select * from member // 고길동,30 //전체검색

트랜잭션2 select * from member  // 고길동,30

트랜잭션1 insert //둘리,5000

트랜잭션2 select * from member // 고길동 30

트랜잭션1 커밋

트랜잭션2 select * from member //고길동 31,둘리 5000 //위에서는 고길동,30이었는데 같은 트랜잭션안에서 row가 증가

트랜잭션2 커밋

 

이런식으로 범위조회를 했을때 다른 트랜잭션의 insert나 delete로 영향을 받아 총 row의 갯수의 변화를 말하는 느낌이다

 

추가적으로 mysql(아마 PostgreSQL도)에서는 기본설정인 repeatable read에서는 일반적인 상황에서는 non-repeatable read나 phantom read까지 전부 나타나지않는다(둘다 스냅샷,즉 언두로그를 활용해서 어케어케함)

 

근데 만약 select ~for update로 비관적 락을 걸었을땐,이땐 팬텀리드 막는거보다 락 거는게 더 중요해서,팬텀리드가 발생할수 있다는걸 염두에 두고,락을 걸기전에 조회를 하지않거나,락을 거는 쿼리의 리턴값을 받아다 쓰는게 좋다

즉 락을 걸땐 제일먼저 거는게 좋다

 

이때도 주의할건,select ~ for update로 락을 걸어도 다른데서 select * from member 이런거로 락 없이 조회때려버리면 쓰기락이고 나발이고 락없는친구한텐 다 뚫리고 그대로 조회 나가니까 이것도 조심