본문 바로가기

DEVELOPER/Database

[DB] 트랜잭션(Transaction)에 대해서 알아보기

안녕하세요😎 백엔드 개발자 제임스입니다 :) 모두 새해 복 많이 받고, 하는 일 모두 잘되세요!

오늘은 트랜잭션에 대해서 정리하겠습니다. 트랜잭션은 데이터베이스를 다루기 위해 필수로 알아야 할 개념입니다. 기술면접에서도 이와 관련된 질문이 자주 나옵니다. 그만큼 기본적이면서 중요하죠. 이제 자세하게 알아보겠습니다.


트랜잭션(Transaction)이란?

간략한 표현 : Tx
1초당 처리할 수 있는 트랜잭션의 개수 : TPS

트랜잭션은 데이터베이스의 상태를 변경시키기 위해 수행하는 작업의 단위입니다. 또는 더 이상 쪼갤 수 없는 업무 처리의 최소 단위입니다. 여기서 상태를 변경시킨다는 의미는 DML(Data Manipulation Language)에 해당하는 SELECT, INSERT, UPDATE, DELETE 등의 명령어에 따른 데이터베이스 내의 데이터 변화를 의미합니다.

트랜잭션의 개념이 직관적이지 않아서 어려울 수 있는데요. 이해하기 쉽게 몇 가지 예를 들어보겠습니다.

* 사례 1
A 회원이 커피 주문 앱으로 커피를 주문하려고 합니다. 아이스 아메리카노 1잔을 선택했고, 결제 버튼을 눌렀습니다. 결제가 성공하고, 데이터베이스에 회원의 주문 내역이 정상적으로 등록되었습니다. 그리고 주문한 커피 수만큼의 스탬프가 찍혔습니다.
* 사례 2
B 회원도 커피 주문 앱으로 커피를 주문하려고 합니다. 아이스 아메리카노 1잔을 선택했고, 결제 버튼을 눌렀습니다. 하지만 잔액이 부족해서 결제에 실패했습니다. 데이터베이스에는 어떠한 변화도 없습니다. 
* 사례 3
C 회원도 커피 주문 앱으로 커피를 주문하려고 합니다. 아이스 아메리카노 1잔을 선택했습니다. 이내 고민을 하다가 카페라떼도 1잔 추가했습니다. 결제를 진행하고, 데이터베이스에 회원의 주문 내역이 정상적으로 등록되었습니다. 그리고 스탬프가 2개 찍혔습니다.

위 사례의 공통점은 무엇일까요?

회원이 요청한 순간부터 데이터베이스에 도달할 때까지 하나의 과정처럼 묶여서 처리되고 있습니다. 각각의 요청은 서로에게 영향을 주지도 않습니다. 이와 같이 데이터베이스에 영향을 가하는 작업의 단위트랜잭션이라고 합니다.

여기서 중요한 점이 있습니다. 이 작업은 논리적 흐름이라는 점입니다. 무조건 여러 개의 작업을 그룹으로 묶는다고해서 트랜잭션이라고 부를 수 없습니다. 물리적으로는 여러 개의 작업이지만 논리적으로는 마치 하나의 작업으로 인식해서 전부 성공하든가, 전부 실패하든가(All or Nothing)의 둘 중 하나로만 처리되어야 트랜잭션의 의미를 가집니다.

* 사례 4 [하나의 논리적 흐름에서 실패한 사례]
D 회원이 커피 주문 앱으로, 아이스 아메리카노 1잔을 주문하려고 합니다. 회원은 잔액이 충분히 있어서 성공적으로 주문할 수 있습니다. 결제를 하려던 순간, 카페라떼도 주문해야 했다는 것이 생각났습니다. 그래서 카페라떼 1잔도 선택하여 다시 결제를 진행했습니다. 하지만 이번엔 잔액부족으로, 주문에 실패했습니다. 데이터베이스에 주문 등록되지 못하고, 스탬프도 받지 못했습니다.
[사례 3]과 [사례 4] 같이, 물리적 흐름은 2개 이상이지만 논리적으로는 한나의 작업이기 때문에 하나의 트랜잭션입니다. 둘의 차이는 '전부 성공하여 데이터 베이스에 반영되었는가', '전부 실패해서 반영되지않았는가'입니다.

잘못된 트랜잭션

트랜잭션은 중요한 의미를 갖습니다. 그 이유는 잘못된 처리는 문제를 야기하기 때문입니다. 아래 예시 외에도 트랜잭션의 원칙을 깨뜨리는 경우에 잘못된 처리로 인지합니다.

  • 상대방에게 돈을 입금하던 도중 네트워크 오류가 발생해서, 내 잔액에는 영향이 없지만 입금이 완료된 경우
  • 커피 주문 앱에서 커피를 주문하는데, 잔액이 부족함에도 불구하고 주문이 성공하는 경우
  • 아이스 아메리카노 1잔을 주문했는데, 2잔이 주문되는 경우
  • 주문은 정상적으로 되었으나, 데이터베이스에 반영되지 않는 경우

트랜잭션 특징

트랜잭션의 특징을 말할 때는 일반적으로 ACID 원칙을 말합니다.

ACID 원칙

1. 원자성(Atomicity)

트랜잭션에서의 원자성이란 작업을 더 이상 쪼갤 수 없음을 의미합니다. 즉, 요청에 대한 결과가 데이터베이스에 모두 반영되던지, 전혀 반영되지 않아야 합니다. 만약 어느 하나라도 오류가 발생하면 트랜잭션의 전부가 취소되어야 합니다.

2. 일관성(Consistency)

일관성은 트랜잭션이 에러 없이 성공적으로 종료될 경우, 비즈니스 로직에서 의도하는 대로 일관성 있게 반영되어야 함을 의미합니다. 말 그대로 커피를 한 개 주문했는데, 데이터베이스애는 두 개로 처리되면 안 됩니다.

3. 격리성(Isolation)

격리성은 여러 개의 트랜잭션이 실행될 경우 각각 독립적으로 실행되어야 함을 의미합니다. 해당 특징은 위에서 언급했던 사례를 통해서도 알 수 있습니다. 회원 A, B, C가 각각 커피를 주문하는데 서로에게 영향을 주어선 안됩니다. 즉, 트랜잭션 수행 시 다른 트랜잭션 연산에 끼어들지 못하도록 보장해야 합니다. 수행 중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서의 수행 결과를 참조할 수 없습니다.

4. 지속성(Durability)

지속성(영속성)은 트랜잭션의 결과가 성공적으로 반영되었다면, 시스템이 고장 나더라도 영구적으로 반영되어야 함을 의미합니다. 월급을 받았는데, 은행 어플에서 서버가 다운되었다고 돈이 사라지면 안 되겠죠 :)


트랜잭션 커밋(Commit)과 롤백(Rollback)

커밋과 롤백은 트랜잭션의 특성을 유지해 줄, 데이터베이스 명령어입니다.

커밋(Commit)

커밋은 하나의 트랜잭션이 성공적으로 끝나고, 데이터베이스가 일관성 있는 상태에 있을 때 하나의 트랜잭션이 끝났음을 알려주기 위해 사용하는 연산입니다. 이러한 커밋은 모든 작업을 최종적으로 데이터베이스에 반영하고, 변경된 내용이 영구적으로 저장됩니다. 만약 커밋을 수행하지 않으면, 결과가 데이터베이스에 반영되지 않습니다.

롤백(Rollback)

롤백은 하나의 트랜잭션 처리가 비정상적으로 종료되어 데이터베이스의 일관성을 깨뜨렸을 때, 원자성을 유지하기 위해 모든 연산을 취소(Undo)하는 연산입니다. 만약 트랜잭션의 일부는 정상적으로 처리되었더라도, 트랜잭션 시작 이 전의 상태로 되돌립니다.


트랜잭션의 상태

  • 활동(Active) : 트랜잭션의 활동 상태입니다. 트랜잭션이 실행 중이며 동작중인 상태입니다.
  • 부분완료(Partially Committed) : 트랜잭션의 Commit 명령이 도착한 상태로, 트랜잭션의 commit 이전 sql 문이 수행되고 commit만 남은 상태입니다.
  • 완료(Committed) : 트랜잭션 완료 상태입니다. 트랜잭션이 정상적으로 완료된 상태입니다.
  • 실패(Failed) : 트랜잭션 실패 상태입니다. 트랜잭션이 더 이상 정상적으로 진행될 수 없는 상태입니다.
  • 취소(Aborted) : 트랜잭션 취소 상태입니다. 트랜잭션이 취소되고 트랜잭션 실행 이전 데이터로 돌아간 상태입니다.

 

* 트랜잭션 사용 시 주의할 점
트랜잭션의 범위는 최소화하는 것이 좋습니다. 일반적으로 데이터베이스 커넥션은 개수가 제한적입니다. 그럼에도 각 단위 프로그램이 커넥션을 소유하는 시간이 길어진다면, 여유 커넥션의 개수가 줄어듭니다. 즉, 각 단위 프로그램에서 커넥션을 가져가기 위해 기다리는 상황이 발생합니다.
반응형