트랜잭션(Transaction)이란?

애플리케이션에서 몇 개의 읽기와 쓰기를 하나의 논리적 단위로 묶는 방법이다. 개념적으로 한 트랜잭션 내의 모든 읽기와 쓰기는 한 연산으로 실행되며, 전체가 성공(COMMIT) 하거나 실패(ABORT, ROLLBACK)한다.

트랜잭션을 쓰면 부분적인 실패를 걱정할 필요가 없어지므로 애플리케이션에서 오류 처리를 하기가 훨씬 단순해진다.

트랜잭션이 제공하는 안전성 보장(ACID)

1983년, 테오 하더(Theo Harder)와 안드레아스 로이터(Andreas Reuter)는 데이터베이스에서 내결함성1 매커니즘을 나타내는 정확한 용어를 확립하기 위해 ACID를 만들었다.

원자성(Atomicity)

여러 쓰기 작업이 하나의 원자적2인 트랜잭션으로 묶여 있는데 결함3때문에 완료(COMMIT)될 수 없다면 어보트되고, 데이터베이스는 이 트랜잭션에서 지금까지 실행한 쓰기를 무시하거나 취소해야 한다.

한 트랜잭션 내의 작업들 중 일부만 성공하는 것은 존재할 수 없다. 만약 어보트되었다면 결론적으로 아무런 변경사항이 없다는 뜻이므로 그냥 재시도 하면 된다.

일관성(Consistency)

ACID의 일관성의 아이디어는 항상 진실이어야 하는, 데이터에 관한 어떤 선언(불변식(invariant))이 있다는 것이다. 예를 들어 회계 시스템에서 모든 계좌에 걸친 대변과 차변은 항상 맞아떨어져야 한다. 트랜잭션이 이런 불변식이 유효한 데이터베이스에서 시작하고 트랜잭션에서 실행된 모든 쓰기가 유효성을 보존한다면 불변식이 항상 만족된다고 확신할 수 있다.

그러나 일관성의 아이디어는 애플리케이션의 불변식 개념에 의존하고, 일관성을 유지하도록 트랜잭션을 올바르게 정의하는 것은 애플리케이션의 책임이다. 데이터베이스는 불변식을 위반하는 잘못된 데이터를 쓰지 못하도록 막을 수 없다.

원자성, 격리성, 지속성은 데이터베이스의 속성인 반면 (ACID에서의) 일관성은 애플리케이션의 속성이다. 애플리케이션에서 일관성을 달성하기 위해 데이터베이스의 원자성과 격리성 속성에 기댈 수는 있지만 데이터베이스만으로 되는 것은 아니다. 따라서 C는 실제로는 ACID에 속하지 않는다.

격리성(Isolation)

동시에 실행되는 트랜잭션은 서로 격리되며, 트랜잭션은 다른 트랜잭션을 방해할 수 없다.

데이터베이스는 실제로 여러 트랜잭션이 동시에 실행됐더라도 트랜잭션이 커밋됐을 때의 결과가 트랜잭션이 순차적으로(하나씩 차례로) 실행됐을 때의 결과와 동일하도록 보장한다.

두 트랜잭션이 동시에 같은 데이터에 접근해도 격리성이 보장되는가?

만약 두 트랜잭션이 동시에 같은 데이터에 접근해도 서로에게 영향을 주지 않는지 궁금해져서 ChatGPT에게 물어봤다.

나: 트랜잭션은 '격리성'이라는 속성을 가진다고 했는데, 만약 두 개의 트랜잭션이 동시에 같은 데이터에 접근해도 서로에게 영향을 미치지 않는거야?

ChatGPT: 트랜잭션 격리성(Isolation)은 동시에 실행되는 여러 개의 트랜잭션들이 각각 독립적으로 실행되는 것처럼 보이도록 하는 것을 의미합니다. 이를 위해 데이터베이스 관리 시스템(DBMS)은 여러 가지 격리 수준을 제공합니다.

하지만 모든 격리 수준에서 완전한 격리가 보장되는 것은 아닙니다. 일부 격리 수준에서는 두 개 이상의 트랜잭션이 동시에 같은 데이터에 접근하면 서로에게 영향을 미칠 수 있습니다. 이러한 문제를 해결하기 위해 DBMS는 다양한 기술을 사용합니다.

가장 높은 격리 수준인 Serializable 격리 수준에서는 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않습니다. 이 격리 수준에서는 두 개 이상의 트랜잭션이 동시에 같은 데이터에 접근하더라도, 하나의 트랜잭션이 모든 작업을 완료할 때까지 다른 트랜잭션이 해당 데이터를 접근할 수 없습니다. 이를 통해 완벽한 격리가 보장됩니다.

하지만 Serializable 격리 수준은 다른 격리 수준에 비해 더 많은 리소스를 요구하고, 성능이 떨어지는 단점이 있습니다. 따라서 DBMS는 보통 Serializable 격리 수준 대신 다른 격리 수준을 사용하며, 개발자는 자신의 애플리케이션에 맞는 적절한 격리 수준을 선택해야 합니다.

나: 두 개의 트랜잭션이 동시에 같은 데이터에 접근했을 때 서로에게 영향을 미칠 수 있는 문제를 해결하기 위해서 Serializable 격리 수준을 사용하지만 성능이 떨어진다는 단점이 있다고 했잖아, 그러면 DBMS는 Serializable 격리 수준 대신 어떤 격리 수준을 사용해?

ChatGPT: DBMS는 Serializable 격리 수준 대신 Read Committed, Repeatable Read, 또는 Snapshot Isolation과 같은 격리 수준을 사용하는 경우가 많습니다. (..생략)

지속성(Durability)

트랜잭션이 성공적으로 커밋됐다면 하드웨어 결함이 발생하거나 데이터베이스가 죽더라도 트랜잭션에서 기록한 모든 데이터는 손실되지 않는다.

단일 노드 데이터베이스에서 지속성은 일반적으로 데이터가 하드디스크나 SSD 같은 비휘발성 저장소에 기록됐다는 뜻이다.

참고 문헌

  • 데이터 중심 애플리케이션 설계 / 마틴 클레프만 저 / 정재부, 김영준, 이도경 역 / 위키북스 / 2021년 10월 20일

주석

  1. fault-tolerant. 결함을 예측하고 대처할 수 있는 시스템 

  2. 더 작은 부분으로 쪼갤 수 없는 무언가 

  3. 프로세스가 죽거나, 네트워크 연결이 끊기거나, 디스크가 가득 차거나, 어떤 정합성 제약 조건을 위반한 경우 등