230419 TIL #63 DB Lock / JPA Lock

김춘복·2023년 4월 19일
0

TIL : Today I Learned

목록 보기
63/571

230419 Today I Learned

실전 프로젝트 3주차. 서버 scale out을 대비해 어떤 락을 걸어야 할지 공부를 했다. Redisson 락을 고려중인데 그 전에 DB lock에 대해 정확한 개념을 알아야 할 것 같아서 오늘 TIL에 정리해보고자 한다.


DB LOCK

  • 동시성 문제 : 공유자원에 대해 동시에 여러 개의 프로세스(혹은 쓰레드)가 접근해 생기는 경쟁 상황. 한 쪽에서 데이터를 수정할 때 다른 쪽에서 수정 전의 데이터를 조회해 로직을 처리하면 데이터의 정합성이 깨지는 문제가 발생한다.

  • JAVA Synchronized : 자바의 Synchronized를 통해 간단하게 동시성 문제를 막고 하나씩 작동하도록 할 수 있지만 여기서는 하나의 프로세스 안에서만 보장이 되기 때문에 서버가 여러 대일 경우 데이터의 정합성이 보장되지 않는다.

  • Lock : 위의 상황에서 데이터의 무결성과 일관성을 지키기 위해 사용되며 트랜잭션 처리의 순차성을 보장하기 위한 방법.

Lock의 종류

  • 공유 락 (Shared Lock, Read Lock, S-lock)
    데이터를 변경하지 않는 읽기 명령에 대해 사용되어지는 Lock. 공유 Lock 끼리는 동시에 접근이 가능하다. 하나의 데이터를 여러 사용자가 동시에 읽을 수 있다는 뜻이다. 하지만 변경(쓰기)은 불가능하다.

  • 배타 락(Exclusive Lock, Write Lock, X-lock)
    데이터를 변경하는 쓰기 명령에 대해 사용되는 Lock. 한 트랜잭션이 LocK을 취득하고 해제하기 전 까지 다른 트랜잭션은 해당 데이터에 접근(읽기, 쓰기)할 수 없다.

Lock의 특징

  • Lock 설정 범위(Level)
    DB, 파일, 테이블, 컬럼, 행(row)에 Lock을 걸 수 있지만 일반적으로는 행(row)에 Lock을 건다.

  • 블로킹(Blocking)
    Lock 간에 경합이 발생해 특정 Transaction이 작업을 진행하지 못하고 멈춘 상태. 공유락끼리는 발생하지 않지만 배타락이 발생 시킨다. 블로킹이 해소되려면 이전의 트랜잭션이 커밋되든 롤백되든 완료가 되어야 한다.
    블로킹을 최소화 하려면 트랜잭션 길이를 줄이고, 격리성을 불필요하게 올리지 않고, 쿼리를 오랜시간 잡아두지 않도록 조정해야 한다.

  • 교착상태(DeadLock)
    두 트랜잭션이 각각의 Lock을 설정하고 서로의 Lock에 접근해 값을 얻어오려고 할때 서로의 Lock때문에 양쪽 트랜잭션이 영원히 처리되지 못하게 되는 상태이다. 교착상태가 발생하면 DBMS가 둘 중 한 트랜잭션에 에러를 발생시킴으로써 문제를 해결한다. 교착상태를 줄이기 위해서는 접근 순서를 동일하게 하는 것이 중요하다.


JPA LOCK

트랜잭션의 격리 수준은 해당 트랜잭션이 다른 트랜잭션에서 변경한 데이터를 볼 수 있는 기준에 대한 정의이다. 반면 JPA의 동시성 제어 메커니즘은 특정 엔티티에 대한 동시 접근을 막기위해 사용된다. 그 방법이 낙관적 락과 비관적 락이다.

낙관적 락(Optimistic Lock)

대부분의 트랜잭션이 충돌이 발생하기 않을 것이라고 낙관적으로 가정하는 방법.
DB에서 제공하는 락 기능을 사용하지 않고, Entity의 버전을 컨트롤 해 동시성을 제어한다.
내가 먼저 이 값을 수정했다고 명시해서 다른 사람이 동일한 조건으로 값을 수정할 수 없게한다.
자원에 락을 걸어 선점하지 말고 커밋할 때 동시성 문제가 발생하면 그때 처리하자는 방법론.
트랜잭션을 커밋하기 전 까지는 충돌여부를 알 수 없다.
어플리케이션 레벨에서 지원하는 락.
트랜잭션을 필요로 하지 않고, 성능적으로 비관적 락보다 좋다.
하지만 충돌이 많이 발생하는 경우 롤백이 많이 발생해 비관적 락보다 성능이 저하된다.

비관적 락 (Pessimistic Lock)

트랜잭션이 시작될 때 공유락이나 배타락을 걸고 시작하는 방법이다.
PESSIMISTIC_READ는 공유락과 유사하게 작동하고, PESSIMISTIC_WRITE는 배타락과 비슷하다.
row에 잠금을 걸어 한 트랜잭션이 끝나기 전까지 다른 트랜잭션이 접근하지 못하고 대기해야한다.
버전의 정보는 사용하지 않는다. DBMS의 락 기능을 사용한다.
트랜잭션이 충돌한다고 가정을 비관적으로하고 락을 건다.
데드락이 발생할 수 있으므로 주의해야 한다.
데이터 수정 즉시 트랜잭션 충돌여부를 확인할 수 있다.

profile
Backend Dev / Data Engineer

0개의 댓글