트랜잭션의 특징 (ACID)

트랜잭션의 특징 (ACID)

트랜잭션이 성공적으로 처리되어 데이터베이스의 무결성과 일관성을 보장하려면 4가지 특성을 만족해야 한다.

1. Atomicity (원자성)

트랜잭션을 구성하는 연산들이 ‘모두 정상적으로 실행’되거나 ‘하나도 실행되지 않아야 한다’는 all-or-nothing 방식을 의미한다.

2. Consistency (일관성)

트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관성 있는 상태를 유지해야 한다. 여기서 말하는 일관성이란, 크게 2가지 의미를 가진다.

  • 첫 번째로, 트랜잭션이 커밋되면 데이터 베이스에 적용한 제약조건(PRIMARY KEY, UNIQUE, NOT NULL 등)을 위반하지 않는다는 보장을 의미한다.

    → 예시) 사용자가 번호를 저장하려고 하는데, 이 번호에 UNIQUE 제약이 설정되어 있으면 중복되니 사용자 번호를 저장할 수 없어야 한다.

  • 두 번째로, 트랜잭션의 작업이 애플리케이션에서 의도하고자 한 작동이 정상적으로 일어난다는 보장을 의미한다.

    → 재고가 떨어졌을 때, 더 이상 판매를 할 수 없도록 제한해야 한다.

3. Isolation (독립성, 격리성, 고립성)

트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것을 의미한다.

예를 들면, 부산의 지정 호텔에 남은 싱글룸 수가 10개였을 때 실제로 숙박하는 로직은 다음과 같다.

  1. 현재 빈 싱글룸의 수를 확인한다(SELECT)
  2. 빈 싱글룸 수에서 1을 빼고 결과를 빈 싱글룸 수로 되돌려 쓴다(UPDATE)
  3. 이것을 사용자 A와 사용자 B가 동시에 수행하면 어떻게 될까? 2명이 방을 확보한다면 원래 빈 싱글룸 수는 2개가 줄어야 하지만, 같은 방을 동시에 확보하게 되면 빈 싱글룸 수는 1개만 줄어들게 된다.

/assets/img/posts/development-database/2021-06-16-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98%20%ED%8A%B9%EC%A7%95%20(ACID)/Untitled.png

이런 사태가 발생하는 것을 막기 위해, 데이터베이스에는 테이블에 대해 Lock(잠금)을 걸어서 후속처리를 Block하는 방법이 있다. 잠금 단위에는 테이블 전체, 블록, 행 등이 있는데, MySQL에서는 트랜잭션 처리를 할 때 주로 행 단위의 잠금 기능을 이용한다. 예를 들어, 앞의 두 가지 중 ‘1. 현재 빈 싱글룸 수를 확인한다’를 처리할 때 ‘SELECT ~ FOR UPDATE’를 실행하면 SELECT한 행에 잠금이 걸린다. 이렇게 되면 후속 처리는 해당 잠금이 해제될 때(COMMIT 또는 ROLLBACK)까지 대기하게 되며 올바른 처리를 계속할 수 있게 된다.

/assets/img/posts/development-database/2021-06-16-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98%20%ED%8A%B9%EC%A7%95%20(ACID)/Untitled%201.png

4. Durability (지속성)

성공적으로 수행된 트랜잭션은 영원히 반영되야 함을 의미한다. 시스템 문제, DB 일관성 체크 등을 하더라도 유지되어야 함을 의미한다. 전형적으로 모든 트랜잭션은 로그로 남고, 시스템 장애 발생 전 상태로 되돌릴 수 있다. 트랜잭션은 로그에 모든 것이 저장된 후에만 commit 상태로 간주될 수 있다.

ACID 원칙은 완벽히 지켜지지 않는다.

실제로는 ACID 원칙은 종종 지켜지지 않는다. 왜냐하면 ACID 원칙을 strict 하게 지키려면 동시성이 매우 떨어지기 때문이다. 그렇기 때문에 DB 엔진은 ACID 원칙을 희생하여 동시성을 얻을 수 있는 방법을 제공한다. 바로 transaction의 격리 수준(isolation level)이다. ACID중 Isolation(독립성) 원칙을 덜 지키는 level을 사용할수록 문제가 발생할 가능성은 커지지만, 동시에 더 높은 동시성을 얻을 수 있다. ANSI/ISO SQL standard에서 정의한 격리 수준에는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABL이 있다.

더 자세한 내용은 밑의 노션 페이지를 참고해라.

잠금(Lock), 블로킹(Blocking), 데드락(DeadLock), 격리 수준(Isolation Level)