트랜잭션(Transaction)

2024. 4. 21. 19:17기술공부

트랜잭션(Transaction)

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

데이터베이스에 접근하는 방법은 쿼리이므로 여러개의 쿼리들을 하나로 묶는 단위를 말합니다.

이에 대한 특성은 원자성, 일관성, 독립성, 지속성이 있으며 이를 ACID특징이라고 합니다.


원자성

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

예를 들어 모든 쿼리문의 수행이 끝나고 커밋하였는데, 문제가 발생했다?? 그러면 처음 상황으로 롤백해야 합니다. 이러한 경우에 쿼리문들은 적용이 되지 않아야 합니다. 이를 보장하는게 원자성 입니다.

커밋 : 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어(트랜잭션 단위로 실행되며 변경된 내용이 영구적으로 저장됨을 의미)
롤백 : 트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 되돌리는 일(수행 취소)

 

커밋 시작 -> 트랜잭션 -> 커밋종료

이 과정에서 커밋 종료 시점에서 데이터베이스에 영구 저장을 하지 않고 다시 처음 시점으로 되돌아가는게 롤백 입니다.

 

일관성

'허용된 방식'으로만 데이터를 변경해야 하는 것을 의미합니다.

 

격리성

트랜잭션 수행 시 서로 끼어들지 못하는 것을 의미합니다. 복수의 트랜잭션은 서로 격리되어 있어 순차적으로 실행되는 것처럼 작동하여야 하고, 여러 사용자는 같은 데이터에 접근해야 합니다.

격리 수준에는 SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITED 이 있습니다.

https://mangkyu.tistory.com/299

 

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

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

mangkyu.tistory.com

 

격리 수준에 따라 발생하는 현상이 있습니다.

1) 팬텀리드(phantom read)

한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우를 말합니다.

ex) 값이 10 이상인 쿼리를 조회 -> 값이 15인 레코드 삽입 -> 다시 값이 10 이상인 쿼리 조회

이러면 뒤에 조회와 앞의 조회 값이 달라지게 됩니다.

새로운 행을 추가할 수 있는 REPEATABLE_READ, 어떤 트랜잭션이 접근 한 행을 다른 트랜잭션에서 수정할 수 있는 READ_COMMITTED, 하나의 트랜잭션이 커밋되기 전에 다른 트랜잭션에 노출되는 문제가 있는 READ_UNCOMMITED에서 발생할 수 있습니다.

 

2) 반복 가능하지 않은 조회(non-repeatable read)

한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 경우를 가리킵니다.

ex) 트랜잭션1이 조회 -> 트랜잭션2가 데이터 값 변경 -> 트랜잭션 1이 같은 조건으로 다시 조회

이 경우에 앞의 조회된 값과 뒤에서 조회된 값이 달라질 수 있습니다.

어떤 트랜잭션이 접근 한 행을 다른 트랜잭션에서 수정할 수 있는 READ_COMMITTED, 하나의 트랜잭션이 커밋되기 전에 다른 트랜잭션에 노출되는 문제가 있는 READ_UNCOMMITED에서 발생할 수 있습니다.

 

3) 더티 리드(dirty read)

반복 가능하지 않은 조회와 유사하며 한 트랜잭션이 실행중일 때 다른 트랜잭션에 의해 수정되었지만 아직 '커밋되지 않은' 행을 읽을 수 있을 때 발생합니다.

ex) 트랜잭션1이 값을 100에서 1로 변경 -> 트랜잭션1이 커밋되기 전이지만 트랜잭션2에서 값을 조회한 결과 100이 아니라 1로 나옴

하나의 트랜잭션이 커밋되기 전에 다른 트랜잭션에 노출되는 문제가 있는 READ_UNCOMMITED에서 발생할 수 있습니다.

 

지속성

성공적으로 수행된 트랜잭션은 영원히 반영되어야 하는 것을 의미합니다. 이는 데이터베이스에 시스템 장애가 발생해도 원래 상태로 복구하는 회복 기능이 있어야 함을 뜻하며, 데이터베이스는 이를 위해 체크섬, 저널링, 롤백 등의 기능을 제공합니다.

 

의문점

트랜잭션 내에서 쿼리문이 발생하는 순서(Spring)

트랜잭션 내에서 쿼리문이 작동하는 순서에 따라 데이터베이스의 값이 다를 것 입니다.

메소드 대로 실행되면 데이터베이스에 저장되는 값이 예측되지만, 만약? 메소드 순서대로 작동하지 않는다면 데이터베이스에 예측과는 다른 값이 저장되는 사태가 일어나게 됩니다.

 

1. UPDATE쿼리는 메서드 순서대로 일어나는 것이 아니라, 영속성 컨텍스트에 엔티티가 올라온 순서대로 발생합니다.

영속성 컨텍스트 : 엔티티를 영구 저장하는 환경(엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리)

A -> B -> C 순서대로 영속성 컨텍스트 생성 C -> B -> A 순서대로 UPDATE 코드를 작성하면 A -> B -> C 순서대로 UPDATE 반영

C -> B -> A 순서대로 영속성 컨텍스트 생성 C -> B -> A 순서대로 UPDATE 코드를 작성하면 C -> B -> A  순서대로 UPDATE 반영

 

2. INSERT는 무조건 DELETE보다 먼저 일어난다

DELETE -> INSERT 순서로 코드를 작성해도 INSERT가 먼저 발생합니다.

-> 외래키 제약조건을 지키기 위해 이런 현상이 일어난다고 합니다. 만약 외래키를 갖는 테이블에 삭제된 데이터가 들어오면 외래키 제약 조건을 위반하게 됩니다.

ex) A테이블의 id는 B테이블의 id를 참조 -> B테이블에 데이터가 하나 지워짐 -> A테이블에 B테이블에서 삭제된 id를 외래키로 갖는 데이터가 들어옴 -> flush메소드가 실행되기 전이면 DELETE가 반영 되지 않았기 때문에 참조 무결성이 깨짐

외래키 제약 조건 : 외래키를 갖는 테이블에 데이터를 먼저 삽입할 때는 기준 테이블에 실제로 존재하는 데이터만 참조해야한다.
참조 무결성 : 외래키 값은 Null이거나 참조 릴레이션의 기본키 값과 동일해야 한다 즉 릴레이션은 참조할 수 없는 외래키 값을 가질 수
없다

 

이를 방지하기 위해서는 DELETE -> flush(db에 DELETE반영) -> INSERT 이렇게 해줘야 한다.

 

참조

https://eocoding.tistory.com/94

https://velog.io/@hubcreator/변경감지-UPDATE-쿼리-생성-순서

'기술공부' 카테고리의 다른 글

Firebase Auth  (0) 2024.04.07
객체지향 프로그래밍(SOILD)  (0) 2024.03.13
지수 백오프(Exponential Backoff)  (0) 2024.03.05
@NoArgsConstructor(access=Level.PROTECTED)  (0) 2023.11.26
AOP(Aspect Oriented Programming)/Spring  (1) 2023.11.20