ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RDBMS 트랜잭션과 락에 대해 (내부 구현)
    DB 2022. 4. 26. 08:50

    트랜잭션을 시작하고, tuple 을 읽는 과정에 대해 RDBMS 에서 어떻게 작동하는지 알아보자.

     

    먼저 lock 을 관리하는 객체를 lock manager 라고 하자. lock manager 는 transaction manager 처럼 추상화된 클래스다. 락을 주세요, 락을 반납할게요 등의 API 를 가지고 있다. RDBMS vendors 에 따라 구현하는 방식이 다르고, 구현 방식에 대한 interface 로 isolation level 이라고 추상화하여 제공한다. 즉, isolation level 은 lock manager 의 구현체가 지켜야 할 룰이라고 볼 수 있다.

     

    예를 들어 이걸 보자. lock manager = lock service, 락을 주세요 = acquire lock, 락을 반납할게요 = release lock

    https://github.com/mysql/mysql-server/blob/8.0/include/mysql/service_locking.h

     

    GitHub - mysql/mysql-server: MySQL Server, the world's most popular open source database, and MySQL Cluster, a real-time, open s

    MySQL Server, the world's most popular open source database, and MySQL Cluster, a real-time, open source transactional database. - GitHub - mysql/mysql-server: MySQL Server, the world's mos...

    github.com

     

    또는 이런 식으로.. API 를 만들 수 있다. (cmu bustub)

    bool LockShared(Transaction *txn, const RID &rid);
    bool LockExclusive(Transaction *txn, const RID &rid);
    bool Unlock(Transaction *txn, const RID &rid);
     
    두 가지 오픈소스에서 lock manager 의 인터페이스를 구현하는 방식은 다르지만, (예를 들어, parameter 로 transaction 객체를 받기 vs 스레드를 받기) 락을 주세요, 락을 반납해요 API 를 구현한다는 점은 동일하다.
     
    트랜잭션A 을 시작하고 tuple A 을 읽고자 한다.

    -> Lock manager 에게 SHARED 락을 요청하고, grant 가 불가할 경우 기다린다. 이는 공유자원에 대해 스레드가 대기하는 것이고 polling 또는 condition_variable 과 sleep queue 를 이용한 방식으로 구현할 수 있다. 

    -> SHARED 락이 grant 되면 트랜잭션은 본인의 작업에 들어간다. (인프런 김영한님 인강에서 Begin - 비지니스 로직 - Commit - Rollback 이렇게 보던데 비지니스 로직에 해당되는 부분이다.) 즉, tuple A 에 대한 읽기 작업을 할 거고 그 후엔, 다른 tuple B 을 읽고 싶어서 그에 대한 SHARED 락을 요청하거나 Commit 하거나 등등.. 을 할 수 있다. 이 동안에 tuple A 에 대한 SHARED 락은 이 트랜잭션A 가 들고 있다.

    -> 다른 트랜잭션B이 같은 tuple A에 작업을 하고 싶을 수도 있다. 읽기를 하고 싶을 때는 SHARED 락을 요청하며, 말 그대로 shared 이기 때문에 같이 쓸 수 있다. 기다리지 않고 grant 될 것이고 작업에 들어간다.

    -> 다른 트랜잭션C가 tuple A 에 쓰기 작업을 하고 싶다. EXCLUSIVE 락을 요청하며, SHARED 락을 가져간 트랜잭션이 있는 경우 가져올 수 없다. (기다려야 한다.) 계속 기다리면 Lock timeout 오류 가 발생한다!! (는 explicit 한 조치를 취했을때 얘기긴 하다.) 

     

    여기서 SHARED 락을 다루는 기준이 isolation level 의 2~3 단계인 REPEATABLE READ, READ COMMITED 에서 다른데, 위의 설명은 2단계인 REPEATABLE READ 기준이다. 단어가 명료한데, REPEATABLE READ 즉, 반복해서 읽을 수 있다 이다. SHARED 락을 트랜잭션 끝까지 들고 있기에, 다른 트랜잭션이 EXCLUSIVE 락을 얻을 수 없다. 따라서, 한 트랜잭션 내에서는 읽기를 반복적으로 수행해도 같은 결과가 나온다. Strict 2 phase locking 으로 트랜잭션 commit 까지 모든 락을 반납하지 않고 가지고 있는 방식이다.

     

    READ COMMITED 에서는 SHARED 락을 트랜잭션 commit 하지 않아도 바로 풀어주며, 따라서 트랜잭션 C가 기다리지 않고 휙득할 수 있다. EXCLUSIVE 락을 원하는 트랜잭션이 SHARED 락을 들고있는 (아마 훨~씬 많은 트랜잭션이 SHARED 를 가지고 있을 것이다.) 트랜잭션을 기다리지 않아도 되므로 성능이 좋아질 것이다. 

     

    Mysql 은 기본이 REPEATABLE READ 일거다. (아마도..) https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html (여기 나온다..) 아직 실제로 옵션을 적용해본적은 없는데 나중에 트래픽이란걸 느껴보면 차이를 느끼지 않을까?

    * Opaque 가 뭘까? spring security 에서 Opaque Token 이 있고 Mysql 에서 Opaque thread handle 이 나오는데 무슨뜻..?

    'DB' 카테고리의 다른 글

    elasticsearch disk 이슈  (0) 2023.03.07
    Real Mysql 내용 정리  (1) 2022.12.18
    Redis 에 대해  (0) 2022.05.27
    Replicas vs Shards  (0) 2022.05.16
    RDB Join 에 대해  (0) 2022.04.10
Designed by Tistory.