- Published on
Transaction에서 Lock 개념
- Authors
- Name
- Chan Sol OH
목차
이번 포스팅은 transaction끼리 충돌을 방지하기위한 데이터 격리와 그 방법인 Lock에대해서 작성한다. transaction에 대한 정보는 Transaction은 무엇일까?와 Transaction Isolation Level 4가지를 참고하면 좋다.
낙관적 Lock과 비관적 Lock
낙관적 Lock
한 데이터에 여러 transaction이 동시에 접근하는 것을 허용하지만, 가장 먼저 commit한 transaction의 변경 사항만 데이터에 적용되고 그 데이터를 수정하려는 나머지 transaction은 예외가 발생한다.
낙관적 Lock은 데이터 수정을 요청할 수 있지만, 실제로 요청될지 안될지는 모르기 때문에 애플리케이션 레벨에서 예외를 처리해줘야한다.
비관적 Lock
한 데이터에 한 transaction만 접근하는 것을 허용한다. 만약 다른 transaction이 읽기나 쓰기를 하려고 하면 예외가 발생하고 Lock이 풀릴 때까지 기다리게된다.
비관적 Lock은 데이터 수정을 요청할 수 없고, 순서대로 처리될 때까지 기다려야한다. 데이터베이스 레벨에서 Lock을 관리하기 때문에 애플리케이션은 time out 예외만 관리하면 된다.
JPA에서 낙관적 Lock
낙관적 Lock을 구현하기 위해 필요한 것은 사용자가 데이터를 업데이트하기 전에 데이터가 다른 사용자로부터 변경되지 않았음을 확인할 수 있어야한다. 이를 위해서 JPA는 엔티티 객체의 필드에 @Version
이라는 어노테이션을 붙여 사용한다.
@Version
어노테이션을 사용하면 JPA가 자동으로 transaction을 시작할 때 해당 필드의 값을 읽고 저장한다. 그 후 사용자가 데이터를 업데이트하고 commit하기 전에 해당 필드를 다시 한번 읽어서 기존 값과 비교한다.
값이 그대로라면 데이터가 업데이트되고 version 필드 값은 증가된다. 만약 값이 바뀌었다면 OptimisticLockException
이 발생된다.
JPA에서 비관적 Lock
JPA는 비관적 Lock을 두가지로 분리해서 적용한다.
- PESSIMISTIC_READ는 transaction이 Lock된 데이터를 읽을 수 있지만, update나 delete는 막는
shared lock
을 제공한다. PESSIMISTIC_READ는 다른 transaction의 update나 delete가 막혀있기 때문에dirty read
를 방지할 수 있다. - PESSIMISTIC_WRITE는 transaction이 Lock된 데이터를 read, update, delete 모두 막는
exclusive lock
을 제공한다. - PESSIMISTIC_FORCE_INCREMENT는 PESSIMISTIC_WRITE와 비슷하지만, 추가적으로 낙관적 lock과 같이 version 필드 값을 증가시킨다.
위 3가지 모두 LockModeType
class의 static 멤버이고, transaction이 db lock을 얻게해준다. 모든 비관적 Lock은 데이터가 commit되거나 roll back 될 때까지 lock이 걸려있다. 만약 다른 transaction이 데이터에 접근하려고 하면 PersistenceException
이 발생된다.