post-thumbnail

Transaction이란 무엇일까?

Transaction
190
4

트랜잭션 (Transaction)

트랜잭션(Transaction)이란 데이터베이스의 상태를 변화시키기 위해서 수행하는 논리적인 작업 단위를 의미합니다. 여기서 데이터베이스의 상태를 변화시킨다는 의미는 질의어 (SELECT, INSERT, DELETE, UPDATE)를 이용하여 데이터베이스에 접근하는 것을 의미합니다. 또한 작업 단위는 정하는 기준에 따라 한번에 모두 수행되어야 하는 일련의 연산을 의미합니다.
현재 저의 블로그의 게시글 생성 작업을 예시로 들어보겠습니다.
1. 게시글 생성 (INSERT)
2. 입력한 태그를 검사하며 존재하는 태그인지 확인 (SELECT)
3. 존재하지 않는 태그는 생성, 기존에 존재하는 태그는 수정 (INSERT/UPDATE)
4. 생성된 게시글을 반환
만약 해당 작업중 3번이 실패한다 가정해보겠습니다.
1. 게시글 생성 (성공)
2. 입력한 태그를 검사하며 존재하는 태그인지 확인 (성공)
3. 태그 생성 중 에러 발생 (실패)
4. 태그가 생성되지 않았지만 게시글이 생성됨 (??)
게시글 생성 중간에 태그를 생성하는 부분에서 에러가 발생했지만 데이터베이스에 게시글이 이미 생성된 상황입니다. 해당 예시처럼 모든 작업이 성공하지 못했을 경우 각 작업의 결과는 데이터베이스의 반영되지 않아야합니다.
이러한 상황을 막기 위해 모든 작업이 성공하면 완전한 거래로 승인(Commit)하고, 거래 도중 오류가 발생했을 경우 거래를 시작하기 전으로 되돌려야 합니다(Rollback).
위 예시처럼 게시글 생성을 하나의 작업 단위, 트랜잭션으로 볼 수 있으며 트랜잭션을 통해 데이터베이스의 안정성을 확보할 수 있습니다.

성질(ACID)

트랜잭션의 성질인 ACID는 데이터의 무결성(Interity)를 보장하기 위해 지켜야할 4가지 특징입니다. 원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 지속성(Durability) 를 의미합니다.

원자성(Atomicity)

트랜잭션 내부의 모든 연산은 모두 성공하여 데이터베이스에 반영되거나 모두 반영되지 않는 성질을 의미합니다. 더이상 쪼갤 수 없는 상태인 원자의 성질을 가졌다는 의미에서 원자성이라고 부릅니다.
앞선 예시처럼 게시글 생성 도중 태그 생성에 실패했다면 기존 진행한 게시글 생성 작업은 데이터베이스에 반영되어선 안됩니다. 이를 위해 작업 실패 시 해당 작업을 Rollback 하여 작업이 실행되기 전 상태로 복구합니다.

일관성(Consistency)

데이터베이스 상태가 일관되어야 한다는 성질입니다. 이는 하나의 트랜잭션 이전/이후 데이터베이스의 상태가 이전과 같이 유효해야 한다는 것을 의미합니다.
"모든 게시글은 제목을 가져야 한다"는 데이터베이스 제약이 존재할 경우 다음 트랜잭션은 일관성을 위반합니다. ```txt
  1. 제목이 존재하지 않는 게시글을 추가하는 작업
  2. 기존 게시글의 제목을 제거하는 작업 ``` 이는 트랜잭션이 실행된 이후 데이터의 상태는 이전과 같이 모순이 없어야 한다는 것을 의미합니다.

격리성(Isolation)

모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다는 의미입니다. 여러 개의 트랜잭션이 동시에 실행될 때, 각 트랜잭션은 고립되어 있어 다른 트랜잭션 연산에 끼어들 수 없으며 수행중인 트랜잭션은 완료될 때까지 다른 트랜잭션의 결과를 참조할 수 없음을 의미합니다.

지속성(Durability)

트랜잭션이 성공적으로 수행되었다면, 해당 트랜잭션에 대한 결과는 영구적으로 반영되어야 한다는 것을 의미합니다. 게시글 생성이 성공한다면 이후 서버가 멈추더라도 데이터베이스에 저장된 게시글에 대한 정보와 기록은 남아야 한다는 것을 예시로 들 수 있습니다.

격리 수준(isolation level)

트랜잭션의 격리 수준(isolation level) 이란 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 고립되어 있는지를 나타내는 것입니다. 간단하게 말해 특정 트랜잭션이 다른 트랙잭션에 변경한 데이터를 볼 수 있도록 허용할 것인지를 경정하는 것입니다.
총 4단계로 구성되어 있으며, 각 단계가 높아질 수록 고립 정도가 높아지지만 성능이 저하됩니다.

[level 0] Read UnCommitted

  • 각 트랜잭션에서의 변경내용이 Commit 이나 Rollback 여부와 상관 없이 다른 트랜잭션이 값을 읽을 수 있습니다.
  • 트랜잭션 작업이 완료되지 않았는데도 다른 트랙잭션의 데이터를 읽는 DIRTY READ 현상이 발생합니다.

[level 1] Read Committed

  • Commit 이 완료된 데이터만 읽을 수 있는 격리 수준입니다.
  • RDB에서 대부분 기본적으로 사용하고 있는 격리 수준으로 실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져옵니다.
  • Read UnCommitted에서 발생하는 DIRTY READ 현상은 발생하지 않지만 하나의 트랜잭션 내에서 작업을 수행했을 때 항상 같은 결과를 가져와야하는 Non-Repeatable Read 현상이 발생할 수 있습니다.

[level 2] Repeatable Committed

  • 데이터 조회시 항상 동일한 데이터 응답을 보장하는 고립 수준입니다.
  • Undo 공간에 백업해두고 실제 레코드 값을 변경합니다. 백업된 데이터는 불필요하다고 판단하는 순간에 주기적으로 삭제하며 백업된 레코드가 많아질 수록 서버처리 성능이 낮아질 수 있습니다.
  • 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상인 PHANTOM READ 현상이 발생할 수 있습니다.

[level 3] Serializable

  • 트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 격리 수준입니다.
  • 가장 엄격한 격리 수준으로 완벽한 읽기 일관성 모드를 제공합니다.
  • 성능 측면에서는 동시 처리성능이 가장 낮습니다.

상태

트랜잭션 상태 변화

트랜잭션 상태 변화

  • 활동(Active) : 트랜잭션의 활동 상태. 트랜잭션이 실행중이며 동작중인 상태를 뜻합니다.
  • 부분완료(Partially Committed) : 트랜잭션의 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태를 뜻합니다.
  • 완료(Committed) : 트랜잭션 완료 상태. 트랜잭션이 정상적으로 완료된 상태를 뜻합니다.
  • 실패(Failed) : 트랜잭션 실패 상태. 트랜잭션이 더 이상 정상적으로 진행될 수 없는 상태를 뜻합니다.
  • 취소(Aborted) : 트랜잭션 취소 상태. 트랜잭션이 비정상적으로 종료되어 Rollback 연산이 실행된 상태입니다.

마치며

원래는 해당 게시글에서 MongoDB에서 Transaction을 사용하기 위해 Replica Set 환경을 구성하는 방법을 작성할 예정이었습니다. 하지만 트랜잭션 관련 게시글을 2개 더 작성할 예정이기 때문에 우선 트랜잭션에 대해 정리하는게 낫다고 판단하여 해당 게시글을 작성했습니다.
트랜잭션 관련 게시글로는 MongoDB Replica Set 환경 구성하기, Transactional Decorator 생성기 를 추가적으로 작성할 예정입니다. 이전 게시글에서 두 달이나 밀려 작성한 게시글이지만 앞으로 꾸준히 업데이트 해나갈 예정입니다 ☺️