Lewis's Tech Keep

[Database] locking 전략과 lock에 관한 이야기 본문

Database

[Database] locking 전략과 lock에 관한 이야기

Lewis Seo 2023. 1. 8. 00:31

계기

사실 글을 쓰게 된 계기가 아주 부끄럽다.

동료 분과 이야기 '낙관적 락'에 대한 이야기를 하다가 나의 무식을 뽐내었기 때문이다.

근래에 '낙관적 락'이라는 단어에 꽂힌 나는 이런 이야기를 하였다.

 

"낙관적 락을 걸면 팬덤 리드의 문제가 없어질 수 있을까요?" 라는 말을 하였고

이에 대해 동료는 매우 의아하게 대답하였다.

 

동료 분은 "낙관적 락 자체가 트랜잭션간의 충돌이 잘 일어나지 않는다고 가정하고 버저닝을 거는 것인데

애초에 그런 상황이 거의 없지 않을까요?" 라고 이야기하였다.

 

나는 그 시점에 회사의 어플리케이션에서 트랜잭션에 락이 걸려있지 않은 부분에서 디버깅을 하다가

트랜잭션 고립 레벨로 인한 이슈 중 팬덤 리드(Phantom Read) 문제가 일어났다고 착오했던 현상이 있었고 잘못 이해하고 있었다.

 

디버깅 시 이러한 상황이었다.

트랜잭션1, 2는 거의 동시에 일어났다.

트랜잭션 1은 A 데이터를 읽고 B로 업데이트 하던 도중에,
트랜잭션 2가 데이터가 읽으려고 하였다.

트랜잭션 2는 데이터의 트랜잭션이 끝나지 않았으므로
트랜잭션 1로 인한 업데이트 되지 않은 데이터 A로 읽었다.


이는 데이터가 오류가 발생하는 원인이 되었다.

 

이러한 상황에서 낙관적 락으로는 트랜잭션을 통째로 실패를 던지게 되지만,
나는 데이터가 존재하는 UPDATE하는 상황이라면 트랜잭션을 실패로 처리하지 않고
그대로 트랜잭션이 커밋되어 통과된다고 생각했다.
(우리 회사는 낙관적 락 전략이 아님에도 낙관적 락이라서 그렇다고 착각
+ 데이터가 업데이트 될 때는 버전에 관계없이 커밋은 계속된다고 착각하였다.)

 

살짝만 찾아봐도 내가 틀렸다는 걸 알았기에 동료에게 사과하였다.

하지만 위의 오류 상황에 대해 이해를 정확히 하지 못한다면 이러한 부끄러운 일들을 내가 계속 저지를 것 같았다.

내가 세세하게 찾아봐야겠다는 생각이 들었다.

그리하여 나는 locking 전략과 lock에 대한 탐험을 하기 시작하게 되었다.


낙관적 락 ? 비관적 락 ? 팬텀 리드?

 

정리하면서 알게된 사실은, 나는 개념을 나누지 않고 혼동하여 사용하고 있었다.

락 전략(낙관적 락, 비관적 락 전략)과 락(트랜잭션 고립 레벨)에 대한 부분을 헷갈렸기 때문이다.

나의 경우, 낙관적 락은 단어가 Optimistic Locking이라서 실제로 레코드 락을 건다고 생각하였다.

 

낙관적 락 전략 과정에서 버전 체크는 시작할 때와 커밋되기 전 일어날 것이라 생각하였고,
이 때 을 걸 것이라 생각하였지만 잘못 생각한 것이었다.

하지만 구글링으론 낙관적 락에 레코드 락을 거는 부분은 없다. 

정리가 필요하다.

 


락전략 과 락(락킹), 트랜잭션 고립 레벨

먼저 나는 이렇게 나누어 생각할 것을 제안한다.

  • 낙관적 락과 비관적 락을 락 전략이라는 하나의 개념,
    트랜잭션 고립 레벨은 으로 락을 관리하기 위한 다른 하나의 개념으로 보아야 한다는 것이다.

  • 낙관적 락, 비관적 락이 실제로 무엇인가 모두 트랜잭션에 lock을 거는 것 처럼 보이지만
    이는 사실이 아니며 그렇지 않고 locking 전략이다.
    • 이 둘의 또 다른 이름은 Optimistic Concurrency Control & Pessimistic Concurrency Control 인데
      이렇게 단어를 두면 실제로 거는 locking 보다는 locking 전략으로 보인다.
  • 락킹은 실제로 데이터베이스에 락을 거는 기술이고
    이 과정에서 읽기 일관성(Read Consistency)를 유지하기 위해 사용된다.
    • 트랜잭션 고립 레벨은 해당 락킹과정에서 고립을 관리하기위한 전략이다.
  • 이 둘은 서로 영향을 미치거나 연관이 있을 수는 있지만 그 자체의 개념이 같지는 않다는 얘기다.

 

하나씩 살펴보자.

 


낙관적 락 전략 & 비관적 락 전략

  • 낙관적 락 및 비관적 락
    • 낙관적 락 특징
      • 낙관적 락 전략(Optimisitic locking 또는 Optimistic Concurrency Control 이라 불림)
      • 낙관적 락은 여러 개의 트랜잭션들이 낮은 확률로 충돌할 것이라 예측하는 전략이다.
        • 충돌이라는 함은 ex. 여러 개의 트랜잭션에서 같은 레코드를 업데이트 하려는 상황
      • 충돌한 순간 충돌된 트랜잭션을 Rollback 한다.
      • 트랜잭션이 레코드 락을 걸지않고 완료된 순간에만 확인한다.
        (주로, 타임스탬프 또는 버전과 같은 것들을 이용하여 버전이 지났는지, 타임스탬프가 옳은 지 확인) 
      • 하지만, 자주 충돌한다면 트랜잭션을 반복적으로 다시 진행해야 하기 떄문에 성능이 매우 낮아진다.
    • 비관적 락 특징
      • 비관적 락 전략 (Pessimistic locking 또는 Pessimistic Concurrency Control 이라 불림)
      • 비관적 락은 여러 개의 트랜잭션들이 높은 확률로 충돌할 것이라 예측하는 전략이다.
      • 업데이트가 필요할 때 마다 레코드 락을 건다.
      • 같은 레코드를 업데이트하려는 다른 트랜잭션은 끝날 때까지 기다린다.
      • 레코드 락을 통해 충돌을 막을 수 있는 장점이 있지만 한 트랜잭션이 끝나기 전까지 다른 트랜잭션이 기다리기 때문에 기다리는 시간이 생긴다.
        • 데드락 가능성도 생김
  • 정리 그림 (참고 그림을 가져왔습니다)

이미지 원본 참고 링크입니다.

 


락(락킹)

  • 데이터베이스에 락을 걸어 다른 트랜잭션에서 한 트랜잭션이 접근하지 못하도록 한다.
  • Read 를 얻기 위한 Shared Lock & Write 를 얻기 위한 Exclusive Lock 이 있다.
  • 이 락을 어느 수준으로 관리하느냐에 따라 비용과 관리 전략이 달라진다.
    • 어느 수준으로 관리 할 것이냐 = 트랜잭션 고립 레벨

 


트랜잭션 고립 레벨

  • 트랜잭션의 고립 레벨이란 트랜잭션들끼리 일관성 있는 데이터를 얼마나 허용할 것인지 정해놓은 수준
  • 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정한다.
  • 트랜잭션 고립은 읽기 일관성을 유지하기 위함
  • 고립 레벨 (고립 수준) 저레벨 >> 고레벨 - 참조
    • Read Uncommited
      • 한 트랜잭션에서 처리 중인 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용
    • Read Commited
      • 트랜잭션이 커밋되어 확정된 데이터만 다른 트랜잭션이 읽도록 허용
    • Repeatable Read
      • 트랜잭션 중 값의 변경에 대해서 일정한 값으로 처리
        • 트랜잭션내에서 삭제, 변경에 대해서 Undo 로그에 넣어두고 
          앞서 발생한 트랜잭션에 대해서는 실제 데이터가 아닌 Undo 로그에 있는 백업데이터를 읽게 함
    • Serializable Read
      • 트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌지 않음은 물론 새로운 레코드가 나타나지도 않도록 하는 설정
  • 고립으로 발생할 수 있는 문제들
    • Dirty Read (Read Commited 이상 일 때 해결)
      • Dirty Read는 다른 트랜잭션에 의해 수정됐지만 아직 커밋되지 않은 데이터를 읽는 것
    • Non-Repeatable Read (Repeatable Read 이상 일 때 해결)
      • Non-Repeatable Read는 한 트랜잭션 내에서 같은 Key를 가진 Row를 두 번 읽었는데 그 사이에 값이 변경되거나 삭제되어 결과가 다르게 나타나는 현상
    • Phantom Read (Serializable 일 때 해결)
      • 한 트랜잭션 내에서 같은 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상

 


결론

 

  • 락전략(낙관적 락, 비관적 락)과 락(락킹)은 각각 다른 개념으로써 분리해서 이해해야 한다.

  • 낙관적 락은 락을 걸지는 않는다.
    • 버저닝, 타임 스탬프 또는 해시값 등등으로 확인하고 다를 때 트랜잭션 전부 실패

  • 비관적 락은 락을 사용한다.
    • 락을 통해 충돌을 방지한다.

  • 트랜잭션 고립 레벨은 락(락킹) 중 읽기 일관성을 관리하기 위한 레벨이다.

  • 낙관적 락으로 트랜잭션 진행 후 커밋 할 때 트랜잭션 고립 레벨이 Read Commited 라면 도움이 된다.
    • Read Uncommited 인 경우 커밋 되기 전 변경된 데이터를 읽을 수도 있는데
      이럴 경우, 데이터 일관성이 깨질 수 있고 자주 실패할 것이다.
      더보기

      If optimistic concurrency control is used with the read uncommitted isolation level, 
      it can lead to lost updates and non-repeatable reads. 
      This is because read uncommitted allows transactions to read data that is not yet committed,
      which means that other transactions could modify the data before it is committed.
      This can lead to situations where one transaction reads data that is later modified by another transaction, resulting in lost updates.
      It can also lead to non-repeatable reads,
      where a transaction reads the same data multiple times and gets different results each time because the data is being modified by other transactions.

      Optimistic concurrency control is designed to prevent these types of issues
      by detecting and resolving conflicts between transactions.
      However, if it is used with the read uncommitted isolation level, it may not be able to properly detect and resolve conflicts, leading to data inconsistencies.
      It is generally recommended to use optimistic concurrency control with a higher isolation level, such as read committed or serializable, to ensure that conflicts are properly detected and resolved.

      ---

      chatGPT에 물어보았다


    • 그래서 낙관적 락의 경우에는 트랜잭션 고립 레벨은 Read Committed 이상으로 하는 것을 추천한다.
    • 그렇다고 깨진 상태로 커밋되는 것이 아니기 때문에 락 전략과 락킹을 다른 개념으로 봐야한다.

 

 

 

 

 


참고 링크

 

락전략 관련

 

Optimistic vs Pessimistic Concurrency: What Every Developer Should Know | .cult by Honeypot

Here are the differences between optimistic and pessimistic concurrency.

cult.honeypot.io

 

Optimistic concurrency control - Wikipedia

Optimistic concurrency control (OCC), also known as optimistic locking, is a concurrency control method applied to transactional systems such as relational database management systems and software transactional memory. OCC assumes that multiple transaction

en.wikipedia.org

 

Concurrency control

Concurrency control is the management of contention for data resources. A concurrency control scheme is considered pessimistic when it locks a given resource early in the data access transaction and does not release it until the transaction is closed. A co

www.ibm.com

 

Optimistic and pessimistic record locking

Overview of optimistic and pessimistic locking implementations in Rational® ClearQuest®. There are two models for locking data in a database: Optimistic locking, where a record is locked only when changes are committed to the database Pessimistic locking

www.ibm.com

 

락 관련

 

when/what locks are hold/released in READ COMMITTED isolation level

I am trying to understand isolation/locks in SQL Server. I have following scenario in READ COMMITTED isolation level(Default) We have a table. create table Transactions(Tid int,amt int) with some

stackoverflow.com

 

[Database] 데이터베이스 락(Lock)의 종류와 역할

데이터베이스는 여러 사용자들이 같은 데이터를 동시에 접근하는 상황에서, 데이터의 무결성과 일관성을 지키기 위해 락을 사용합니다. 데이터베이스의 락은 크게 3종류로 분류할 수 있습니다.

velog.io

 

락 전략과 트랜잭션 고립 레벨 관계 관련

 

How are locking mechanisms (Pessimistic/Optimistic) related to database transaction isolation levels?

I am writing a web application where two different users can update a list of things, to do list, for example. I have come to realize that, optimistic locking mechanism works best since I don't exp...

stackoverflow.com

 

트랜잭션 고립 레벨

 

[데이터베이스] 트랜잭션과 격리성

안녕하세요. 평소에 포스팅하던 내용과는 조금 떨어진 이론적인 내용을 포스팅하고자 합니다. DB는 트랜잭션 단위로 처리된다고 합니다. 유명한 All Or Nothing이 DB의 트랜잭션에서 나온 이야기입

sabarada.tistory.com

 

[DB] 트랜잭션의 고립(격리) 수준(Isolation Level) | 고립 수준 예시

트랜잭션의 고립 수준(Isolation Level)이란? 트랜잭션의 고립 수준이란 트랜잭션들끼리 일관성 있는 데이터를 얼마나 허용할 것인지 정해놓은 수준이다. 즉, 트랜잭션 수행 중 다른 트랜잭션이 해

code-lab1.tistory.com

 

트랜잭션의 격리 수준(isolation Level)이란?

 

nesoy.github.io

 

데이터베이스 트랜잭션과 고립화 레벨

트랜잭션 (Transaction) what: 데이터베이스의 상태를 변환시키는 작업 단위를 이야기 한다.

unluckyjung.github.io

 

데이터 베이스 락

 

데이터베이스 - Exclusive lock과 Shared lock의 차이

Exclusive lock과 Shared lock 운영체제에서 잠금(Lock)과 유사하게 데이터베이스에서도 잠금(Lock)이 있다.멀티 트랜잭션 환경에서 데이터베이스의 일관성과 무결성을 유지하려면 트랜잭션의 순차적 진

jeong-pro.tistory.com

 

Comments