트랜잭션

MoMoon·2023년 9월 12일

DB

목록 보기
1/2

트랜잭션

  • 하나의 논리적 기능을 수행하기 위한 작업의 단위
  • 논리적인 이유로 여러 SQL문들을 단일 작업으로 묶어서 나눠질 수 없게 만든 단위

동작

(1) commit

  • 트랜잭션이 정상적으로 이루어져서 데이터베이스에 데이터를 반영한 경우

(2) rollback

  • 에러가 발생하였을 때 지금까지 작업들을 모두 취소하고 이전 상태로 되돌리는 경우
  • Transaction은 결과 값을 바로 반영하지않고 임시로 결과 값을 저장해놓는다

AUTOCOMMIT

  • SQL문을 자동으로 Transaction하게 처리해주는 기능
  • Mysql에서는 default로 enable 되어있음

하지만 여러 SQL문을 Transactin 처리하고 싶다면 AutoCommit를 disable하고 사용해야된다
Mysql로 예를 들면

START TRANSACTION; // 해당 구문을 통해 AutoCommit 속성이 자동으로 disable
UPDATE member SET name = "Lee" WHERE id = 1;
UPDATE member SET name = "Kim" WHERE id = 2;
COMMIT; // COMMIT / ROLLBACK 에서 transaction이 종료되면 자동으로 enable

현재까지 정리하자면

1) Transaction 시작 SQL (AutoCommit 속성 disable)
2) 로직 수행
3.1) 문제 없다면 COMMIT를 통해 데이터 반영
3.2) 문제가 발생했다면 ROLLBACK를 통해 이전 상태로 되돌림
4) Transaction 종료 시 (AutoCommit 속성 enable)

속성 (ACID)

1) Atomicit (원자성)

  • 논리적으로 쪼갤 수 없는 단위이기 때문에 트랜잭션의 결과가 데이터 베이스에 모두 반영되거나 반영 되지않아야 된다
  • 트랜잭션 내의 모든 명령은 반드시 수행되어야되며, 어느 하나가 에러가 발생하면 트랜잭션의 전부 rollback

2) Consistency (일관성)

  • 트랜잭션의 데이터베이스의 상태(기본키 및 여러 조건)들이 일관성 있게 유지되어야한다
  • DB에 정의된 제약사항을 transaction이 위반하였다면 rollback

3) Isolation (독립성)

  • 둘 이상의 트랜잭션이 동시에 실행되고 있을 경우에도 각각 따로 실행되어야한다
  • 수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다

이 속성은 DB 성능과 관련있는 속성이다

  • DBMS는 isolation level를 제공하는데 이는 해당 level에 따라 해당 동시성 이슈를 어떤 레벨로 처리할 지 정할 수 있다
    • 해당 속성이 높을수록 보다 엄격하게 관리하기 때문에 여러 트랜잭션을 동시에 실행시킬 수 없어서 성능이 떨어지게 된다

4) Durability (지속성)

  • 트랜잭션이 성공적으로 완료되었을 경우, 결과는 영구적으로 저장한다
  • 일반적으로 비휘발성 메모리(HDD, SDD..)에 저장함을 의미

트랜잭션이 동시에 실행되면

트랜잭션은 여러 트랜잭션이 동시에 실행되어도 마치 각각 격리되어 다른 트랜잭션의 영향을 받지않고 동작하는 isolation 속성을 보장해야된다
이를 보장하기 위해 serializablity와 recoverablility를 제공한다

1. Serializablity

  • serial schedule을 동시에 사용하기 위한 속성

트랜잭션은 스레드와 같이 동시에 접근하면 동시성 이슈가 발생할 수 있다
이를 lost update라고 하는데 밑에 사진을 보면

재고가 12가 남아있었고 모두 합쳐서 5개가 팔렸다. 그러면 총 재고가 7개가 남아야한다.
하지만 동시에 접근하게 되면서 데이터를 읽은 시점의 차이가 발생하여 stock의 update가 잘못된 경우이다.

schedule

  • 여러 transaction들이 동시에 실행되었을 때 각 transaction에 속한 연산들의 실행 순서
  • 각 transaction 내의 연산 순서는 바뀌지않는다

1) Serial schedule

  • transaction들이 겹치지 않고 한 번에 하나씩 실행되는 경우

성능적인 측면에서 한번에 하나의 트랜잭션만 실행되기 때문에 좋은 성능은 기대할 수 없지만 정확한 결과가 나온다.

2) Nonserial schedule

  • lost update와 같이 transaction이 겹쳐서 실행되는 경우

성능적인 측면에서 한번에 여러 트랜잭션을 실행하기 때문에 많은 트랜잭션을 처리할 수 있다.
즉, 성능적인 측면에서 좋지만 lost update와 같은 이상한 결과가 나올 수 있습니다.
이를 해결하고자 나온 개념이 Conflict 개념입니다

Conflict

아래 3가지 조건이 부합하면 Conflict라고 한다

1. 서로 다른 trasaction
2. 같은 데이터 접근
3. 최소 하나의 transaction은 write

위 사진을 보면 2번의 read-write conflict와 1번의 write-write conflict가 발생하였다.

이 conflict 연산은 순서가 바뀌면 결과도 바뀝니다

Conflict equivalent

두 조건을 모두 만족하면 conflict equivalent

	1. 두 schedule은 같은 transaction을 가진다
    2. 어떤 confliting 연산 순서도 양쪽 schedule 모두 동일하다

위 사진에서 각각의 Conflict의 연산 순서가 전부 동일하다면 같은 Schedule로 보는 것입니다.
이처럼 Serail schedule하고 Conflict equivalent 상태일 때 Conflict serializable이라고 합니다.
그러면 오른쪽도 Noneserial schedule이지만 Conflict serializable합니다.

2. Recoverability

  • 여러 트랜잭션이 동시에 실행되었을 때 rollback과 관련된 속성

K의 계좌에서 H로 20만원 이체하는 T1, H가 20만원 입금하는 T2가 동시에 발생하였다고 가정

1) recoverable schedule

t1 ==================
read(K_balance = 100) 
write(K_balance = 80)
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t1====================
read(H_balace = 120) // t2의 write(H_balance = 120)에 의존성이 있다
write(H_balance = 140)
======================
t2 commit
---------------------
t1 commit
  • 의존성이 있는 t2가 종료가 될 때까지 t1는 commit하면 안된다
  • 만약 t1를 먼저 commit해버리면 Durability 속성에 의해 롤백이 불가능하다.
    • lost update가 발생할 수 있다
  • 여러 trasaction의 rollback이 연쇄적으로 일어날 수 있다
    • 처리하는 비용이 많이 든다

2) cascadeless schedule

t1 ==================
read(K_balance = 100) 
write(K_balance = 80)
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t2 commit // t2 종료 에러가 발생해도 해당 t2만 롤백하면 된다
t1====================
read(H_balace = 120) 
write(H_balance = 140)
t1 commit
  • recvoerable schedule의 연쇄적인 rollback을 보완하기 위한 schedule
  • 데이터를 write한 trasaction를 commit/rollback한 후에 데이터를 읽는 schdule

3) strict schedule

t1 ==================
read(K_balance = 100) 
write(K_balance = 80)
read(H_balace = 120) 
write(H_balance = 140)
t1 commit
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t2 commit
  • schedule 내에서 어떤 trasaction도 commit 되지 않은 transaction들의 write한 데이터를 쓰지도 읽지도 않은 schedule
  • rollback 할 때 recovery가 쉽다

3. concurrency control ( 동시성 제어 )

  • DBMS에서 serializability와 recoverability를 제공하는 기능

트랜잭션 내의 이상 현상

1) dirty read

  • commit 되지않은 변화를 읽음

2) nonrepeatable read

  • 같은 데이터의 값이 달라짐

3) phantom read

  • 트랜잭션 내의 없던 데이터가 생김

isolation level

  • DB 성능을 위해 이상 현상을 어느정도 타협하는 정도
Isolation levelDirty readNon-repeatable readPhantom read
Read uncommittedOOO
Read committedXOO
Repeatable readXXO
SerializableXXX

snapshot isolation

concurrency control를 어떻게 구현할 지 정의해놓은 isolation level

특징

  • 트랜잭션마다 snapshot으로 관리된다
  • 트랜잭션이 시작하는 시점을 기준으로 데이터베이스 값들을 읽어온다
    • 그래서 t1 snapshot에서는 y를 50으로 불러오게된다
  • 같은 데이터를 write하는 경우 먼저 commit한 t2만 반영하고 t1는 rollback

Propagation

트랜잭션 내부에서 또 다른 트랜잭션을 진행할 때 어떻게 할지 결정하는 기법이다

  • 물리 트랜잭션: 실제 데이터베이스에 적용되는 트랜잭션, 커넥션을 통해 커밋/롤백하는 단위
  • 논리 트랜잭션: 스프링이 트랜잭션 매니저를 통해 트랜잭션을 처리하는 단위

속성

1) REQUIRED (default)

  • 부모 트랜잭션이 존재한다면 부모 트랜잭션에 합류, 아니라면 새로운 트랜잭션
  • 중간에 예외가 발생하면 자식과 부모 모두 rollback

2) REQUIRES_NEW

  • 무조건 새로운 트랜잭션을 만든다
  • rollback은 각각 이루어진다

3) MANDATORY

  • 무조건 부모 트랜잭션에 합류
  • 부모 트랜잭션이 없다면 예외

4) REQUIRES_NEW

  • 항상 새로운 트랜잭션이 필요함
  • 기존 트랜잭션이 없다면 새로운 트랜잭션을 생성, 있다면 기존 트랜잭션을 보류시키고 새로운 트랜잭션을 생성

5) NOT_SUPPORTED

  • 트랜잭션을 지원하지 않는다

6) NEVER

  • 트랜잭션을 사용하지않는다 (기존 트랜잭션마저도 허용하지않음)
  • 기존 트랜잭션이 있다면 예외 발생

7) NESTED

  • 중첩(자식) 트랜잭션을 생성함
  • 기존 트랜잭션이 있다면 중첩 트랜잭션을 만듬

참고 문헌

https://easy-code-yo.tistory.com/26
https://mangkyu.tistory.com/269

0개의 댓글