ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DB Lock
    연습장 2024. 10. 17. 13:21

    1. DB Lock

    1.1 개념

      데이터베이스에서 여러 트랜잭션이 동시에 같은 데이터에 접근할 때, 데이터의 무결성(일관성)을 보장하기 위해 사용되는 메커니즘.

     

      한 트랜잭션이 특정 데이터에 대해 작업을 하고 있을 때, 다른 트랜잭션이 그 데이터에 접근하지 못하도록 잠그는 것. 데이터의 일관성 유지 및 동시에 발생할 수 있는 충돌을 방지

     

    1.2 필요성

      DB 락을 통해 데이터에 대한 접근을 제어하면, 다음과 같은 상황에서 발생할 수 있는 데이터 무결성 문제를 예방할 수 있음.

     

    - Dirty Read: 한 트랜잭션이 데이터를 수정 중일 때 다른 트랜잭션이 그 데이터를 읽는 상황

    - Non-repeatable Read:  한 트랜잭션이 데이터를 읽은 후, 다른 트랜잭션이 그 데이터를 수정하고 커밋하여 첫 번째 트랜잭션이 동일한 데이터를 다시 읽을 때 값이 달라지는 상황.

    - Lost Update: 두 개의 트랜잭션이 동시에 같은 데이터를 수정하려고 할 때, 한 트랜잭션의 수정 내용이 다른 트랜잭션에 의해 덮어쓰여져 사라지는 상황.

     

    2. 락의 종류

    - 공유 락(Shared Lock, S Lock) : 데이터베이스에서 데이터를 읽을 때 사용. 여러 트랜잭션이 동시에 같은 데이터를 읽을 수 있지만, 공유 락이 걸린 동안에는 데이터를 수정할 수 없음.

     

    - 배타 락(Exclusive Lock, X Lock): 데이터를 수정할 때 사용. 배타 락이 걸린 데이터는 다른 트랜잭션이 읽거나 수정할 수 없음. 한 트랜잭션이 배타 락을 획득하면 다른 모든 트랜잭션은 해당 데이터에 접근할 수 없음.

     

    - 비관적 락(Pessimistic Locking): 데이터를 읽을 때부터 락을 걸어 다른 트랜잭션이 접근하지 못하도록 하는 방식. 데이터의 충돌 가능성이 높을 때 유용.

     

    - 낙관적 락(Optimistic Locking): 데이터를 수정하기 전까지 락을 걸지 않고, 수정 시점에만 충돌을 확인하는 방식. 주로 데이터의 버전 번호를 사용하여 동시성 문제를 해결.

     

    - 명명된 락(Named Lock): 데이터베이스에서 특정 이름으로 락을 설정하여, 동시에 하나의 프로세스만 특정 리소스에 접근하도록 하는 방식. 주로 특정 리소스나 작업에 대한 접근을 직관적으로 제어하기 위해 사용.

     

    - 분산 락(Distributed Lock): 여러 시스템이나 인스턴스에서 동시에 동일한 자원에 접근할 때, 자원의 일관성을 유지하기 위해 사용되는 락. Redis와 같은 분산 시스템을 사용하여 구현.

     

     

    2.1. 비관적 락

    종류

      - Pessimistic Read: 읽기 락(Shared Lock)을 설정하여, 다른 트랜잭션이 해당 데이터를 읽을 수는 있지만, 수정은 할 수 없도록 함.

      - Pessimistic Write: 쓰기 락(Exclusive Lock)을 설정하여 다른 트랜잭션이 해당 데이터를 읽거나 수정하지 못하도록 함.

     

    DB 레벨에서의 락 동작

      - 락 설정: 비관적 락을 사용하면 SQL쿼리나 트랜잭션이 데이터베이스에 접근할 때 락이 설정.

      - 락 해제: 일반적으로 트랜잭션이 종료되거나 커밋될 때 해제. 롤백되는 경우에도 락이 해제. 

     

    비관적 락은 주로 데이터베이스 레벨에서 동작, 데이터 무결성을 보장하는 데 매우 유용.

    그러나 DB레벨에서 동작하기 때문에 성능에 영향을 미칠 수 있으므로, 데이터 충돌 가능성이 높은 환경에서 신중하게 사용해야 함.

    스프리부트와 같은 애플리케이션에 서 비관적 락을 설정하면, 데이터베이스가 이 락을 처리하고 관리하게 됨.

     

    비관적 락이든, 낙관적 락이든, 이거를 설정했다고 해서 충돌이 완벽하게 해소되었다. 라고 표현할 수 없음. 환경에 따라 달라지기 때문. 

    따라서 어느 정도의 요청량이 들어올 거라는 것을 파악해야 함. 너무 많은 요청이 온다면, DB Lock보다 메시지 큐(RabbitMQ, Kafka)를 사용하여 쓰기를 대기열에 넣어서 지연시키는 방법으로 하는 것이 더 안전.

     

    2.2 낙관적 락

    동작방식

      - 낙관적 락(Optimisitc Lock)은 트랜잭션 간의 충돌을 최소화하고 성능을 향상시키기 위해 사용되는 동시성 제어 메커니

        즘.

     

      - 비관적 락이 데이터베이스 레벨에서 락을 걸어 다른 트랜잭션의 접근을 차단하는 방식이라면, 낙관적 락은 DB락을            사용하지 않고, 대신 데이터가 변경되었는지 확인하여 충돌을 처리하는 방식.

     

      - 버전 관리:

        - version이라는 필드를 엔티티에 추가하여, 해당 엔티티의 수정 횟수를 추적.

        - 트랜잭션이 엔티티를 읽을 때, 현재의 버전 번호가 함꼐 읽혀옴.

        - 트랜잭션이 엔티티를 수정하고 저장하려고할 때, 현재 데이터베이스에 저장된 버전 번호와 트랜잭션이 처음 읽어온            버전 번호를 비교.

     

      - 데이터 충돌 검출

        - 트랜잭션이 데이터를 저장할 때, 데이터베이스에 저장된 버전 번호가 트랜잭션이 처음 읽어온 버전 번호와 동일하다          면, 데이터가 수정되지 않았다고 간주하고 업데이트를 수행. 이때 버전 번호는 증가.

        - 반면, 버전 정보가 다르다면, 다른 트랜잭션이 데이터를 수정한 것으로 간주하고, 현재 트랜잭션을 롤백하거나 재시도

     

    장단점

      - 장점:

        - 성능: DB락을 걸지 않으므로 병행 처리 성능 향상.

        - 유연성: 충돌이 발생했을 때, 비즈니스 로직에 따라 트랜잭션을 재시도하거나 롤백할 수 있음.

      - 단점:

        - 충돌 가능성: 데이터가 자주 변경되는 경우, 충돌이 자주 발생할 수 있음. 이로 인해 여러 번의 재시도 필요 가능.

        - 복잡성: 충돌을 처리하기 위한 로직이 추가로 필요.

     

    낙관적 락은 데이터베이스 락을 최소화하면서도 데이터 일관성을 유지할 수 있는 효과적인 방법임.

    특히, 데이터 충돌이 적고 병행 처리가 많은 시스템에서 유용하게 사용할 수 있음.

    하지만, 충돌이 발생했을 때의 처리 로직을 잘 설계해야 하며, 특정 상황에서는 비관적 락보다 복잡할 수 있음.

     

    2.3 데드 락

    데이터베이스 환경에서 데드락은 2개 이상의 트랜잭션이 서로가 점유하고 있는 자원을 기다리면서 영원히 대기 상태에 빠지는 상황을 의미.

    이 상황이 발생하면, 해당 트랜잭션들은 더 이상 진행될 수 없고, 시스템 성능에 큰 영향을 미칠 수 있음.

     

    예시

      - 트랜잭션A는 테이블 X의 일부 행을 잠금(Lock)하고 이후 테이블 Y의 행을 잠금하려고 시도

      - 트랜잭션B는 Y의 일부 행을 잠금하고, 이후 테이블 X의 행을 잠금하려고 시도

      - 이 경우, 트랜잭션 A와 B는 서로 상대방이 보유한 잠금을 기다리면서 영원히 대기하게 되며, 이로 인해 데드락 발생

     

Designed by Tistory.