Back_End(Ruby on Rails)

Rails Transaction Isolation Level (트랜잭션 격리 레벨)

swdream 2020. 2. 10. 20:20
반응형

트랜잭션 격리 레벨에 대해서 찾아본 이유는, 예전에 유저 등의 랭킹 시스템을 만드는 프로젝트를 맡은 적이 있었습니다. 배치 프로그램으로 매일 마다 갱신된 랭킹을 db에 삽입하는 기능을 구현해야 했는데, Transaction을 걸어서 all or not 으로 한번에 데이터를 커밋하고자 하였었습니다. 여기서 더 궁금했던 점은 랭킹 산출을 위해서는 실시간 유저의 스코어가 필요했는데, 랭킹 반복 연산 도중에 유저의 정보가 바뀌면 이것이 어떻게 저장되지? 라는 의문점에서 격리레벨이라는 것을 더 찾아보게 되었었네요. 이 결과, Backend 개발에서는 트랜잭션 격리 레벨을 만들어두고, 데이터의 특성이나 비즈니스 로직에 따라 격리 레벨을 달리 준다는 것을 알게 되었습니다. 

Transaction 을 먼저 짚고 넘어가면, Transaction은 DB에 접근하고 다양한 아이템들을 업데이트(혹은 Create)하는 단위 프로그램 실행을 의미합니다. 한 단위로 이루어진 것이 중요합니다. 컴퓨터 관점에서는 여러 개의 연산이지만, 사용자 관점에서는 일련된 하나의 행동인 경우를 컴퓨터로 실행할 때 트랜잭션을 사용합니다. 예로 들면, 은행 거래를 할 때 주는 사람과 받는 사람의 계좌는 정확히 양측 모두에게 빠지고 더해져야 하나의 완결된 행동이므로, 이런 데이터의 완결성을 지키기 위해 트랜잭션을 사용하는 것입니다. 

아래와 같은 1, 2번 싸이클로 이루어진 여러개의 연산들을 트랜잭션은 한 번에 실행합니다. 

  • Read: 데이터를 읽은 후 변수에 저장하여,(보통 연산 등을 하고)
  • Write: 이러한 데이터를 db에 쓰는 작업을 합니다.

이런 트랜잭션은 크게 4가지 특성이 있습니다. 1번 Isolation 관련해서는 성능 튜닝을 위해 크게 4개 정도의 Isolation Level을 DBMS에서 갖고 있습니다.

  1. Isolation: (다른 트랜잭션들과 격리가 되어 독립적으로 트랜잭션이 일어납니다.)
  2. Atomicity: (All or None.. 은행 계좌 거래를 떠올리면 됩니다. 주는 사람 받는 사람의 계좌 모두에 데이터 증/감이 반영되어야 거래가 제대로 일어난 것임..)
  3. Durability: 
  4. Consistency: 트랜잭션 내 데이터는 일관성을 유지해야 함  

여러 Transaction들이 동시에 일어날 수 있고 서로 읽어오거나 쓰는 db 에 영향을 줄 수 있는데, 이 때 적절한 isolation level을 설정하여 트랜잭션을 합시다..  아래 Isolation Level 별 특성입니다.

  1. Serializable: Usually Ensures Serializable Execution.. 즉, 대개는 순서를 지키는 연산을 처리하게 합니다. (가장, 빡쎈 격리 레벨입니다.)
  2. Repeatable Read: 트랜잭션 중 타 트랜잭션에서 Commit된 데이터만 읽을 수 있는 정도의 격리 레벨입니다. 다만, 외부 트랜잭션에서 커밋된 데이터 중 기존 데이터에 대해 Update된 데이터는 읽기를 허용하지 않고 격리합니다.. 다만, 외부에서 Insert Commit된 데이터는 읽을 수 있습니다.  Mysql에서는 Isolation Level 기본값이기도 합니다.. (참고로 Postgress 에서 격리 레벨의 기본값은 read_uncommitted) 
  3. Read Committed: 트랜잭션 중 타 트랜잭션에서 Commit된 데이터만 읽을 수 있습니다. 외부 트랜잭션에서 커밋된 데이터 중 Insert로 새 데이터 추가 뿐 아니라, Update Commit된 데이터도 읽을 수 있습니다. 
  4. Read Uncommitted: 트랜잭션 중 타 트랜잭션에서 커밋되지 않은 데이터도 읽을 수 있는 정도의 낮은 격리 레벨입니다.. 타 트랜잭션에서 begin transaction 이후 commit이 되기 전에 insert, update 등이 된 데이터에 대해서도 내가 속한 트랜잭션에서 해당 데이터를 읽을 수 있습니다. 

레일즈에서 Transaction Isolation level에 대한 언급없이 트랜잭션을 실행하면 연동된 DBMS에 디폴트로 주는 격리 레벨에 맞게 트랜잭션이 일어납니다. 즉, Mysql을 dbms로 쓴다면, Repeatable Read로 격리 레벨이 설정됨(MySQL 의 디폴트는 Repeatable Read 입니다.)

 

반응형