Transaction A.C.I.D , Transaction 격리레벨

짱구·2023년 1월 19일
0

database

목록 보기
2/7

  • Atomicity(원자성)
    • 트랜잭션과 관련된 작업들이 부분적으로 실행되다 중단되지 않음을 보장해야한다.
    • 하나의 기능은 무조건 ALL(전체 성공) or NOTHING(전체 실패)
  • Consistency(일관성)
    • 트랜잭션 실행이 성공하고 완료가 되었을 때는 항상 일관성있는 데이터베이스로 유지해야한다.
  • Isolation(독립성)
    • 트랜잭션을 수행할 때 다른 트랜잭션 연산 작업이 끼어들지 못하도록 보장해야한다.
    • 트랜잭션 밖에 있는 어떠한 연산도 중간 단계(현재 트랜잭션)의 데이터를 볼 수 없다.
    • 성능관련 이유로 인해 이특성은 가장 유연성 있는 제약 조건이다.
  • Durability(지속성)
    • 트랜잭션이 성공적으로 수행되었을 경우 트랜잭션은 영원히 반영되어야 한다.

Atomicity

ex)

라이언이 어피치에게 2000원을 송금했다.

  • 트랜잭션 시작
    • {라이언 잔액} -> InnoDB undo log에 저장
    • {어피치 잔액} -> InnoDB undo log에 저장
    • ( update {라이언 잔액} = {라이언 잔액} - 2000 ) -> DB에 적용
    • ( update {어피치 잔액} = {어피치 잔액} + 2000 ) -> DB에 적용

transaction commit
※undo log는 바로 delete 되지 않음

else)

  • 트랜잭션 시작
    • {라이언 잔액} -> InnoDB undo log에 저장
    • {어피치 잔액} -> InnoDB undo log에 저장
    • ( update {라이언 잔액} = {라이언 잔액} - 2000 ) -> DB에 적용
      error 발생

transaction rollback
-> InnoDB undo log에 저장되어 있는 데이터로 데이터베이스 덮어쓰기


Consistency

ex)

제약조건으로 Consistency를 유지 - > unique , foreign key


Isolation

ex)

트랜잭션은 서로 간섭하지 않고 독립적으로 동작
-> 많은 성능을 포기해야하므로 개발자가 제어 가능
-> 트랜잭션 격리레벨을 통해 제어


Durability

ex)

데이터베이스 성능에 핵심은 Random I/O의 양
Update, Insert와 같은 쓰기 작업이 일어날 때 마다 디스크에 데이터를 밀어 넣는 것은 성능에 안좋은 영향을 줌

그래서 메모리에 데이터 작업을 먼저 실행한다
-> 메모리는 휘발성을 가져 데이터가 유실되면...?
-> WAL(write ahead logging)로 어느정도 해소

WAL

  • 순차적으로 데이터 로그를 쌓는것
    • 로그를 쌓는 타이밍은 설정값을 통해 제어가 가능
    • 메모리가 휘발되어 데이터가 날아가도 데이터베이스가 켜질 때 Redo Log(WAL)를 보고 데이터를 다시 쌓는다.

문제점

Dirty Read

  • commit 되지 않은 데이터를 읽은 상황

ex)

transaction1 == 라이언이 어피치에게 2000원을 보내는 상황
transaction2 == 조회를 하는 상황

라이언의 잔액 3000원 , 어피치의 잔액 100원

transaction1 - 
1. select id, priceAcount from member where id="라이언" and id="어피치";
   id = 라이언, priceAcount = 3000, id = 라이언, priceAcount = 100
transaction1 - 
2. update member set priceAcount = priceAcount - 2000 where id="라이언";
   update member set priceAcount = priceAcount + 2000 where id="어피치";
3. transaction1 - 트랜잭션에 오류가 발생 
	rollback;
4. transaction2 - 어피치가 조회한 상황
 select id, priceAcount from member where id="어피치";

transaction2 어피치가 가져온 정보는 어피치의 잔액 2100원

※ 어피치의 잔액이 2100원이고 롤백되기 전에 데이터를 가져온 상황


Non Repeatable Read

  • 한 트랜잭션 안에서의 결과값이 다르고 다른 트랜잭션의 영향을 받은 상황

ex)

transaction1 == 라이언이 잔액 조회를 3번 실행
transaction2 == 어피치가 라이언에게 500원을 송금

라이언의 잔액 3000원

transaction1 - 
1. select id, priceAcount from member where id="라이언";
   id = 라이언, priceAcount = 3000
transaction1 - 
2. select id, priceAcount from member where id="라이언";
   id = 라이언, priceAcount = 3000
transaction2 - 
3. update member set priceAcount = priceAcount + 500 where id="라이언";
   commit;
transaction1 - 
4. select id, priceAcount from member where id="라이언";
   id = 라이언, priceAcount = 3500    

transaction1이 가져온 정보는 라이언의 잔액 3500원

※ 라이언의 잔액이 한번에 트랜잭션 내에서 결과값이 다름


Phantom Read

  • 같은 조건으로 데이터를 읽었을 때 없던 데이터가 생기는 경우

ex)

transaction1 == 잔액이 1000원 이상인 사람들을 조회
transaction2 == 잔액 100원이 있던 어피치의 계좌에 2000원이 입금

라이언의 잔액 3000원

transaction1 - 
1. select id, priceAcount from member where priceAcount >= 1000;
   id = 라이언, priceAcount = 3000
transaction2 - 
2. update member set priceAcount = priceAcount + 2000 where id="어피치";
   commit;
transaction1 - 
3. select id, priceAcount from member where id="라이언";
   id = 라이언, priceAcount = 3000 , id = 어피치, priceAcount = 2100

transaction1이 가져온 정보는 라이언만 조회되어야 하는데 어피치까지 포함하여 결과값이 변경


트랜잭션 격리레벨 설정

Read Uncommitted : 3가지 격리수준을 모두 허용 (거의 안씀)

Read Committed : Dirty Read만 허용 X (가장 많이 씀)

Repeatable Read : Phantom Read만 허용
(많이 쓰이지만 deadLock 이슈 때문에 Read Committed보다 적게 쓰임)

Serializable Read : 모두 허용 X (거의 안씀)

출처 및 링크 : fastcampus

profile
코드를 거의 아트의 경지로 끌어올려서 내가 코드고 코드가 나인 물아일체의 경지

0개의 댓글