트랜잭션(transaction)

김명일·2022년 5월 31일
0

트랜잭션이란?

mysql 공식문서에서 트랜잭션은 커밋되거나 롤백될 수 있는 atomic한 일의 단위라고 말합니다.

  • atomic: 원자성. 더이상 나눌 수 없는
  • 커밋: 변경사항을 데이터베이스에 적용하는 것을의미합니다.
  • 롤백: 변경사항을 데이터베이스에 적용하지 않고 커밋되기 이전 상태로 되돌리는것을 의미합니다.
    즉, 더이상 나눌 수 없이 모든 변경사항이 데이터베이스에 적용되거나 적용하기 이전으로 되돌리는 것을 의미합니다.

트랜잭션은 ACID 특징을 같습니다.

  • Atomic(원자성): 트랜잭션 연산이 모두 반영되거나 모두 반영되지 않는 특징
    - autocommit, commit, rollback
  • Consistency(일관성): 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성있는 데이터베이스 상태로 변경됨
  • Isolation(격리성): 둘 이상의 트랜잭션이 실행되는 경우, 다른 트랜잭션 연산에 끼어들 수 없음
  • Durability(지속성): 성공한 트랜잭션 연산은 무슨일이 있어도 영구적으로 반영되어야 함 - 이를 위해, 쓰기시 중복하여 따로 저장합니다.

Locking

트랜잭션의 ACID한 특징을 위해 Locking이 사용됩니다.
Locking은 다른 트랜잭션에 의해 쿼리되거나 변경되는 데이터를 보거나 변경하지 못하도록 하는 것을 말합니다.
Locking은 데이터의 일관성을 보장하기 좋지만 성능적 저하가 있을 수 있기에 일관성과 성능사이에서 적절하게 사용해야합니다.


Isolation level

트랜잭션에는 격리수준이 존재합니다. 격리수준도 역시 성능과 일관성, 신뢰성 사이에서 적절한 수준을 사용해야 합니다. 격리수준은 해당 세션에서만 적용되게도 할 수 있고 이후에 연결되는 세션에 모두 적용되게도 할 수 있습니다. 디비 트랜잭션 설정

Consistent Read란
Consistent Read는 같은 시간에 실행되는 다른 트랜잭션에 관계없이 쿼리의 결과를 특정한 시점에 데이터를 일관성있게 제공해주기위해 snapshot을 사용하는 것을 말합니다. 만약 다른 트랜잭션에서 읽은 데이터를 수정하는 경우, 원래 있던 데이터는 undo log에 기록되어 조회됩니다. 이로 인해, locking없이 일관성있는 읽기를 제공하게됩니다.

또한 일반적으로 InnoDB에서는 READ COMMITTED, REPEATABLE READ의 격리 수준에서는 SELECT문이 Consistent read를 수행하는 것이 default입니다.

Mysql InnoDB에서는 총 4가지 격리수준이 존재합니다.

REPEATABLE READ

Mysql InnoDB에서 default로 설정되는 격리수준으로, 첫 번째 읽기 연산시Consistend read를 제공합니다. 만약 A트랜잭션에서 읽어온 데이터를 B트랜잭션에서 변경하더라도 A트랜잭션에서 다시 읽을 경우, undo log에 있는 처음 읽은 데이터를 그대로 읽어오게 되어 일관성 있는 읽기를 제공합니다.

READ COMMITTED

READ COMMITTED에서는 각각의 Consistent Read시 새로운 스냅샷이 생성됩니다. 즉, InnoDB에서는 default로 SELECT가 Consistent Read이므로, SELECT시 마다 새로운 snapshot이 생성되게 됩니다.

그러므로 A트랜잭션에서 데이터를 읽고, B트랜잭션에서 해당 데이터를 수정 및 커밋한 후, A트랜잭션에서는 다시 읽을 경우 수정된 데이터가 조회됩니다.

또한 READ COMMITTED에서는 gap lock이 사용되지 않고 record lock만 사용된다. 따라서 Phantom Read가 발생할 수 있다.(같은 범위의 읽기 연산시, 첫 번째 조회에서 없던 데이터가 두 번째 조회에서 생기는 것)

idc1
110
39

위 와같은 테이블 t1에서 아래와 같은 순서로 실행되는 경우, A트랜잭션에서 첫번째 SELECT와 두번째 SELECT가 다르게 나타나게 된다.

A트랜잭션B트랜잭션
SET transaction_isolation = "READ-COMMITTED"SET transaction_isolation = "READ-COMMITTED"
begin;
SELECT * FROM t1 WHERE c1 BETWEEN 9 and 10;
begin;
INSERT INTO t1(c1) VALUES(9);
commit;
SELECT * FROM t1 WHERE c1 BETWEEN 9 and 10;

READ UNCOMMITED

READ UNCOMMITED는 다른 트랜잭션에서 커밋되지 않은 정보를 읽어오는 격리수준이다. 이러한 현상을 dirty read라고 한다. 이 부분을 제외하고는 READ COMMITED와 동일하다.

예시) 1과 2에서 조회되는 데이터가 변경된다.

idc1
110
23
A트랜잭션B트랜잭션
SET transaction_isolation = "READ-UNCOMMITTED";SET transaction_isolation = "READ-UNCOMMITTED";
begin;
SELECT * FROM t1; --- 1
begin;
UPDATE t1 SET c1 = 1 WHERE id = 1;
commit;
SELECT * FROM t1; --- 2

SERIALIZABLE

REPEATABLE READ 격리 수준과 비슷하다. autocommit되지 않는 경우 SELECT문을 SELECT ... FOR SHARE로 변경하게 된다. 따라서 s lock이 걸리므로 변경이 불가능하다. 만약 autocommit이 활성화 되어있다면 SELECT문이 하나의 트랜잭션이 된다.

profile
주니어 백엔드 🐶🦶🏻📏

0개의 댓글