티스토리 뷰

CS 정리/DB

트랜잭션

tose33 2023. 10. 22. 13:47

트랜잭션이란

데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위.

디비에 접근 하는 방법은 쿼리이므로 여러개의 쿼리를 하나로 묶는 단위.

트랜잭션의 특징은 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability) 가 있다.

(ACID)

 

 

원자성 (Atomicity) 

트랜잭션에 관련된 일이 모두 수행되었거나 되지 않았거나를 보장하는 특징.

트랜잭션을 커밋했는데 문제가 발생해 롤백하는 경우 그 이후에 모두 수행되지 않음을 보장하는 것을 말함.

 

예를들어 1000만원을 가진 A가 0원을 가진 B에게 500만원을 이체하는 경우 다음과 같은 operation 단위들로 이루어진 과정을 거친다.

 

1. A의 잔고를 조사

2. A에게서 500만원을 뺀다

3. B에게 500만원을 더한다.

 

디비 사용자는 1~3의 과정을 볼 수도 참여할수도 없고 모든게 끝난 이후 A가 500만원, B가 500만원을 갖고 있다는 것만 본다.

만약 이 작업을 롤백하면 1~3 이 모두 한꺼번에 롤백된다.

(Save point 를 이용하면 중간까지 롤백할수도 있다) 

 

트랜잭션 전파란?

트랜잭션은 하나의 커넥션을 Connection 을 가져와 사용하다가 닫는 사이 일어난다.

여러 트랜잭션 관련 메서드의 호출을 하나의 트랜잭션에 묶이도록 하는 것이 트랜잭션 전파.

또는 어떤 트랜잭션이 동작중인 과정에서 다른 트랜잭션을 실행할 경우 어떻게 처리하는가? 에 대한 개념.

 

예를들어 spring 에서는 @Transactional 로 여러 쿼리 관련 코드들을 하나의 트랜잭션으로 처리한다.

@Transactional 은 여러 트랜잭션을 하나의 거대한 트랜잭션 경계를 만들수 있다.

기존에 트랜잭션이 진행 중 일때 또 다른 트랜잭션을 진행해야 하는 경우가 있는데, 

이때 기존의 트랜잭션에 참여, 에러 발생, 별도의 트랜잭션으로 진행 할 수 있다.

이것을 트랜잭션 전파 속성 이라고 한다.

 

 

일관성 (Consistency)

허용된 방식으로만 데이터를 변경해야 하는 것.

트랜잭션의 작업 처리는 항상 일관성이 있어야 한다.

db에 기록된 모든 데이터는 여러 가지 조건, 규칙에 따라 유효함을 가져야 한다.

 

예를들어 A가 1000만원이 있고 B가 0원이 있다.

B가 A에게 500만원을 입금하는 것은 불가능하다.

 

예를들어 작성 테이블의 본문 내용 글자 제한이 255 글자일때, 트랜잭션이 일어나면 글자 제한 조건을 만족해야만 트랜잭션이 수행되고 위반한다면 거부해야 한다.

즉 트랜잭션 수행 전, 후에 데이터 모델의 모든 제약 조건 (기본키, 외래키,도메인,도메인 제약조건 등)을 만족해야 한다.

 

트랜잭션의 일관성 보장은 트리거 를 통해 보장한다.

트리거는 특정 테이블에 insert,delete,update 같은 dml 문이 수행되었을 때,

db에서 자동으로 동작되도록 작성된 프로그램.

예를들어 한쪽 db의 테이블에 수정이 일어났을 경우, 다른쪽 테이블도 함께 수정되도록 자동 업데이트하게 함.

 

 

격리성 (isolation)

트랜잭션 수행 시 서로 끼어들지 못하도록 보장하는 것.

복수의 병렬 트랜잭션은 서로 격리되어 마치 순차적으로 실행되는 것처럼 작동되어야 한다.

 

트랜잭션의 격리 수준

https://mangkyu.tistory.com/299

 

[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기

이번에는 트랜잭션 격리 수준(Isolation Level)에 대해 알아보도록 하겠습니다. 아래의 내용은 RealMySQL과 MySQL 공식 문서 등을 참고하여 작성하였으며, 모든 내용은 InnoDB를 기준으로 설명합니다. 해당

mangkyu.tistory.com

격리성은 여러 개의 격리 수준으로 나뉘어 격리성을 보장한다.

여러 트랜잭션이 동시에 처리 될때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 여부를 결정하는 것.

 

<-- 격리성 높음  ----------------------------------------------  동시성 높음 -->

SERIALIZABLE,  REPEATABLE_READ,  READ_COMMITTED,  READ_UNCOMMITTED

 

 

SERIALIZABLE

가장 엄격한 격리 수준.

트랜잭션을 순차적으로 진행 시킴.

여러 트랜잭션이 동일한 테이블에 동시 접근 불가능하므로 데이터 부정합 문제 없음.

하지만 순차적으로 진행시키기 때문에 성능이 매우 떨어짐.

가장 안전하지만 성능이 매우 떨어지므로, 극단적으로 안전한 작업이 필요한 경우 아니면 사용하지 않음.

 

REPEATABLE READ

보통 rdbms 는 변경 전 레코드를 언두 공간에 백업해둔다.

그러면 변경 전 후 데이터가 모두 존재하므로 동일한 레코드에 대해 여러 버전의 데이터가 존재한다 (Multi-Version Concurrency Control)

이를 통해 트랜잭션이 롤백된경우 데이터 복원 가능.

 

REPEATABLE_READ 는 MVCC 를 이용해 한 트랜잭션 내에서 조회시 동일한 결과를 보장한다.

(하지만 새로운 레코드가 추가되는 경우에는 부정합이 생길수 있다 (팬텀리드)) 

사용자 B 가 id=50 레코드를 조회하고 있다.

(트랜잭션은 숫자가 부여되는데 여기서 T-ID=10 이다) 

아직 B 의 트랜잭션이 끝나지 않은 상황에서 A가 id=50 레코드를 업데이트 한다.

 

그러면 데이터는 변경되지만 기존 데이터는 언두 로그에 백업된다.

이 상태에서 B가 (트랜잭션이 아직 종료되지 않음) 또 다시 select 로 id=50 레코드를 조회하게 되면 

B의 트랜잭션 번호는 10이고, A는 12이다.

B의 트랜잭션이 먼저 시작했기 때문에 REPEATABLE_READ 는 트랜잭션 번호를 참고해 자신보다 먼저 실행된 트랜잭션의 데이터만 조회한다.

테이블에 자신 이후에 시작된 트랜잭션의 데이터가 존재하면 언두로그를 참고해 데이터를 조회한다.

 

따라서 여기서 A의 트랜잭션은 데이터를 변경후 커밋까지 되었지만, B의 트랜잭션 이후에 실행되었기 때문에 언두로그를 참고해서 B가 변경하기 이전의 데이터를 조회한다.

 

즉 REPEATABLE_READ 는 어떤 트랜잭션이 읽은 데이터를 다른 트랜잭션이 수정하더라도 동일한 결과를 반환할것을 보장한다.

 

 

팬텀 리드

REPEATABLE_READ 는 새로운 레코드의 추가까지는 막지 않는다.

따라서 조회한 경우 트랜잭션이 끝나기 전에 다른 트랜잭션에 의해 추가된 레코드가 발견될수있다.

이를 팬텀리드 라고 한다.

 

하지만 MVCC 를 통해 자신보다 늦게 시작한 트랜잭션이 추가한 레코드는 무시하면 되기 때문에 일반적으로 발생하지 않는다.

(MYSQL 은 특수한 갭락이 존재하는데 이것 때문에 발생할수도 있다 ) 

 

 

READ_COMMITTED

READ_COMMITTED 는 커밋된 데이터만 조회할수 있다.

이 격리수준은 팬텀리드, non-repeatable read(반복 가능하지 않은 조회) 문제가 발생한다.

 

예를들어 A 가 트랜잭션을 시작해 어떤 데이터를 변경하고 아직 커밋하지 않은 상태다.

이때 B가 데이터를 조회하려고 하면 READ_COMMITTED 에서는 커밋된 데이터만 조회할수 있으므로 REPEATABLE_READ 때와 마찬가지로 언두 로그에서 변경 전의 데이터를 찾아서 반환한다. 

최종적으로 A가 커밋을 하면 이제 다른 트랜잭션에서도 새롭게 변경된 값을 참조할수 있다.

 

반복 가능하지 않은 조회 문제는 다음과 같다.

B가 id=10 을 조회하는데 이때 아직 해당 데이터가 없어서 아무것도 리턴하지 않았다.

B가 아직 커밋하지 않은 상태에서 A가 id=10 의 레코드를 추가하고 커밋했다.

아직 커밋하지 않은 B가 이때 또다시 id=10 을 조회하면 READ_COMMITTED 는 커밋한 데이터를 조회할수 있으므로 A가 추가한 결과가 나오게 된다.

 

이렇게 READ_COMMITTED 에서 하나의 트랜잭션에서 반복 읽기를 하면 다른 트랜잭션의 커밋 여부에 따라 조회 결과가 달라질수 있다.

 

 

READ_UNCOMMITTED

커밋하지 않은 데이터 조차도 접근 할 수 있는 격리 수준.

 

이 격리 수준은 더티 리드(Dirty read) 라는 문제가 발생할수 있다.

이는 어떤 트랜잭션의 작업이 완료되지 않았는데 다른 트랜잭션에서 볼 수 있는 문제다.

 

예를들어 A가 트랜잭션을 시작하고 데이터를 insert 하고 아직 커밋하지 않았다.

이때 B가 해당 데이터를 읽었다.

이후 A가 롤백을 한다.

이후 B가 다시 데이터를 읽으면 롤백 됐으므로 있던 데이터가 없어진 것이다.

 

READ_UNCOMMITTED 는 있던 데이터가 사라지는 매우 심각한 상황을 초래하는 문제가 발생할수 있어 표준으로 인정되지 않을 정도로 위험한 격리 수준이라 거의 사용하지 않는다.

 

 

 

 

 

 

격리 수준이 높아질 수록 성능이 떨어질까?

SERIALIZABLE 을 제외하면 그렇게 차이 나지 않는다.

이유는 언두 로그를 통해 레코드를 참조하는 과정이 거의 동일하기 때문이다.

 

오라클은 READ_COMMITTED 를 기본으로, MYSQL 에서는 REPEATABLE_READ 를 기본으로 사용한다.

 

 

 

지속성 (Durability)

성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다는 것을 의미.

이는 디비에 시스템 장애가 발생해도 원래 상태로 복구하는 회복 기능이 있어야 함을 뜻한다.

이를 위해 체크섬, 롤백 등을 제공한다.

 

체크섬이란 중복 검사의 한 형태로, 오류 정정을 통해 송신된 자료의 무결성을 보호하는 단순한 방법.

저널링이란 변경 사항을 커밋하기 전에 로그에 남기는 것. (MVCC) 

 

 

 

 

동시성 제어 (Concurenccy Control) 

동시에 실행되는 여러 개의 트랜잭션이 작업을 성공적으로 마칠 수 있도록 트랜잭션의 실행 순서를 제어하는 기법

db 는 다중 사용자 환경을 지원하므로 동시에 실행되는 트랜잭션이 성공적으로 마칠수 있도록 지원해야 한다.

 

 

즉 트랜잭션의 직렬화 수행 보장.

 

 

낙관적 동시성 제어

사용자들이 같은 데이터를 동시에 수정하지 않을 것이라고 가정.

잠금을 사용하지 않는 대신, 레코드의 버전 등을 통해 수정 시점에 변경 여부를 검사함.

트랜잭션 수행 동안은 어떠한 검사도 하지 않고, 트랜잭션 종료 시에 일괄적으로 검사함.

 

비관적 동시성 제어 

사용자들이 같은 데이터를 동시에 수정할 것이라고 가정.

공유락, 베타락 등과 같은 잠금을 사용하는 방식으로, 시스템의 동시성을 심각하게 떨어뜨릴수 있으므로 wait 또는 nowait 옵션과 함께 사용해야함.

 

 

잠금 (Locking)

https://velog.io/@ha0kim/%EC%9E%A0%EA%B8%88Locking-%EA%B8%B0%EB%B2%95

 

잠금(Locking) 기법

잠금의 정의잠금(Locking)은 하나의 트랜잭션이 실행하는 동안 특정 데이터 항목에 대해서 다른 트랜잭션이 동시에 접근하지 못하도록 상호배제(Mutual Exclusive) 기능을 제공하는 기법이다. 하나의

velog.io

 

잠금은 하나의 트랜잭션이 실행하는 동안 특정 데이터 항목에 대해 다른 트랜잭션이 동시에 접근하지 못하도록 상호배제 기능을 제공하는 기법.

 

하나의 트랜잭션이 데이터에 대해 잠금을 설정하면, 잠금을 설정한 트랜잭션이 해제할 때 까지 데이터를 독점적으로 사용할수 있다.

 

공유락은 (LS, Shared Lock) 트랜잭션이 읽기를 할 때 사용하는 락, 데이터를 읽을 수 있지만 쓸 수 없음.

트랜잭션1 에서 x에 대해 공유락을 설정했다면 트랜잭션2 에서도 그동안 읽기만 가능하다.

 

베타락은 (LX, Exclusive Lock) 트랜잭션이 읽고 쓰기를 할 때 사용하는 락, 데이터를 읽고 쓸 수 있음.

트랜잭션1에서 x에 대해 베타락을 설정했다면 트랜잭션2는 그동안 읽기도 쓰기도 불가능하다.

 

 

 

 

'CS 정리 > DB' 카테고리의 다른 글

RDBMS vs NoSQL  (0) 2023.10.23
커넥션 풀  (0) 2023.10.23
정규화  (0) 2023.10.22
인덱스, 페이지  (0) 2023.10.22
  (0) 2023.10.21
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함