[Database] (쉬운 코드) 트랜잭션과 ACID
쉬운 코드 강의 「데이터베이스」 내용을 바탕으로, 데이터베이스 트랜잭션(transaction)과 트랜잭션의 주요 속성인 ACID에 대한 내용을 정리한 포스트 입니다.
아래의 내용은 MySQL 기준으로 작성한 것입니다. 다른 RDBMS의 SQL 문법은 조금씩 다를 수 있습니다.
transaction
데이터베이스에서 트랜잭션(transaction)은 다음과 같은 작업을 의미한다.
- 단일한 논리적인 작업 단위(a single logical unit of work)
- 논리적인 이유로 여러 SQL문들을 단일 작업으로 묶어서 나눠질 수 없게 만든 것이 transaction이다.
- transaction의 SQL문들 중에 일부만 성공해서 DB에 반영되는 일은 일어나지 않는다.
ex. A가 B에게 20만원을 이체하는 상황을 DB에 반영하기 위해서는 아래 쿼리문이 모두 정상적으로 잘 작동해야한다.
UPDATE account SET balance = balance - 200000 WHERE id = "A"UPDATE account SET balance = balance + 200000 WHERE id = "B"
만약 둘 중에 하나라도 실패하면 DB에 반영되지 않아야한다.
위의 예시를 트랜잭션으로 구현해보자.
1
2
3
4
START TRANSACTION;
UPDATE account SET balance = balance - 200000 WHERE id = "A";
UPDATE account SET balance = balance + 200000 WHERE id = "B";
COMMIT;
COMMIT- 지금까지 작업한 내용을 DB에 영구적으로(permanently) 저장
- transaction을 종료
ex. 추가로 A가 B에게 30만원 이체한 것을 transaction으로 구현
1
2
3
4
5
6
START TRANSACTION;
UPDATE account SET balance = balance - 300000 WHERE id = "A";
select * from account
--- A는 -30만원이지만 아직 B는 +30만원이 반영되지 않는 상태를 출력 ---
ROLLBACK;
--- A는 다시 -30만원이 반영되지 않은 상태로 되돌아간다. ---
ROLLBACK- 지금까지 작업들을 모두 취소하고 transaction 이전 상태로 되돌린다.
- transaction을 종료한다.
1
2
3
4
5
6
7
8
SELECT @@AUTOCOMMIT;
-- 결과값이 1이면 아래 쿼리문이 자동으로 실행됨 --
insert into account values ('W', 1000000);
SET autocommit=0;
DELETE FROM account WHERE balance <= 1000000;
-- autocommit이 0이기 떄문에 rollback을 한다면 다시 이전 상태로 돌아갈 수 있다. --
ROLLBACK;
AUTOCOMMIT- 각각의 SQL문을 자동으로 transaction 처리를 해주는 개념
- SQL문이 성공적으로 실행하면 자동으로 commit 하여 영구적으로 변경된 데이터가 저장된다.
- 실행 중에 문제가 있었다면 알아서 rollback 한다.
- MySQL에서는 default로 autocommit이 enabled 되어 있다.
- 다른 DBMS에서도 대부분 같은 기능을 제공한다.
- 실행이 된다면 1로 설정되어 있고, 실행이 안된다면 0으로 설정되어 있다.
START TRANSACTION에서의 AUTOCOMMIT
START TRANSACTION실행과 동시에 autocommit은 off 된다.COMMIT / ROLLBACK과 함께 transaction이 종료되면 원래 autocommit 상태로 돌아간다.
transaction 사용 패턴
일반적으로 transaction은 다음과 같은 패턴으로 사용된다.
- transaction을 시작(begin)한다.
- 데이터를 읽거나 쓰는 등의 SQL문들을 포함해서 로직을 수행한다.
- 로직 수행이 끝난 후,
- 일련의 과정들이 문제없이 동작했다면 transaction을 commit한다.
- 중간에 문제가 발생했다면 transaction을 rollback한다.
ACID
ACID는 트랜잭션이 가져야 할 4가지 주요 속성을 의미한다.
Atomicity
- ALL or NOTHING
- transaction은 논리적으로 쪼개질 수 없는 작업 단위이기 때문에 내부의 SQL문들이 모두 성공해야 한다.
- 중간에 SQL문이 실패하면 지금까지의 작업을 모두 취소하여 아무 일도 없었던 것처럼 rollback 해야한다.
여기서 DBMS는 commit를 실행 시 DB에 영구적으로 저장하는 것과 rollback 시 이전 상태로 되돌리는 것을 DBMS가 담당하는 부분이다.
개발자는 언제 commit 하거나 rollback을 할지를 챙겨야한다.
Consistency
만약, A가 B에게 20만원을 이체하는 상황에서 A의 잔액이 10만원이라면, A가 B에게 20만원을 이체하는 것은 불가능하다. 따라서 A의 잔액이 음수가 되는 일은 일어나지 않아야한다.
이렇게, 데이터베이스에 저장된 데이터가 일관성을 유지해야 한다는 것을 의미한다.
- transaction은 DB 상태를 consistent 상태에서 또 다른 consistent 상태로 바꿔줘야한다.
- constraints, trigger 등을 통해 DB에 정의된 rules을 transaction이 위반했다면 rollback 해야한다.
- transaction이 DB에 정의된 rule을 위반했는지는 DBMS가 commit 전에 확인하고 알려준다.
- 그 외에 application 관점에서 transaction이 consistent하게 동작하는지는 개발자가 챙겨야 한다.
Isolation
만약, A가 B에게 20만원을 이체할 때 B도 ATM에게 본인 계좌에 30만원을 입금한다면 어떻게 될까?
A가 B에게 20만원을 이체하는 도중에 B가 ATM에서 30만원을 입금한다면 A가 B에게 이체한 금액이 반영되기 전의 B의 잔액을 기준으로 이체 금액이 계산될 수도 있다.
위 예시의 경우 여러 transaction들이 동시에 실행하면 문제가 발생할 수 있다. 즉, 여러 transaction이 실행에 있어 서로에게 영향을 주지 않아야하기 때문에 Isolation 이 중요하다.
- 여러 transaction들이 동시에 실행될 때도 혼자 실행되는 것처럼 동작하게 만든다.
- DBMS는 여러 종류의 isolation level을 제공한다.
- 레벨이 높을수록 isolation이 강해지고, 동시에 실행되는 transaction의 수가 줄어든다.
- isolation이 높을수록 동시성이 떨어지므로 성능 또한 떨어진다.
- 개발자는 isolation level 중에 어떤 level로 transaction을 동작시킬지 설정할 수 있다.
- concurrency control의 주된 목표가 isolation이다.
Durability
commit된 transaction은 DB에 영구적으로 저장된다. 이를 Durability를 의미한다.
- 여기서 영구적이란 DB system에 문제(power fail or DB crash)가 생겨도 commit된 transaction은 DB에 남아 있는다.
- 영구적으로 저장한다 라고 할 때는 일반적으로 ‘비휘발성 메모리(HDD, SSD, …)에 저장함’을 의미한다.
- 기본적으로 transaction의 durability는 DBMS가 보장한다.
참고사항
- transaction을 어떻게 정의해서 쓸지는 개발자가 정하는 것이다.
- 구현하려는 기능과 ACID 속성을 이해해야 transaction을 잘 정의할 수 있다.
- transaction의 ACID와 관련해서 개발자가 챙겨야 하는 부분들이 있다.
- DBMS가 모든 것을 알아서 해주는 것은 아니다.
