개발은 개념싸움이야🫠

[DB] 트랜잭션(transaction) 과 격리성 수준

hyunki.Dev 2023. 10. 23. 19:52

📌 트랜잭션이란

-  트랜잭션이란 한 번 질의가 실행되면 질의가 모두 수행되거나 모두 수행되지 않는 작업수행의 논리적 단위입니다.

- 질의(query)를 하나의 묶음 처리해서 만약 중간에 실행이 중단됐을 경우, 처음부터 다시 실행하는 Rollback을 수행하고, 오류없이 실행을 마치면 commit을 하는 실행 단위를 의미합니다.

 

- 트랜잭션은 작업수행의 논리적 단위이므로 DBMS의 성능을 초당 트랜잭션 실행 수(TPS : Transaction per second)로 측정합니다.

- 데이터베이스 트랜잭션은 ACID 라는 특성을 가지고 있습니다.


📌 ACID

  • 데이터베이스 내에서 일어나는 하나의 트랜잭션의 안정성을 보장하기 위해 필요한 성질입니다.

Atomicity (원자성)

  • 한 트랜잭션 내에서 실행한 작업들은 하나의 작업으로 간주. 모두 성공 또는 실패되어야 한다.
  • 트랜잭션의 작업이 부분적으로 실행되거나 중단되지 않는 것을 보장하는 것을 말합니다.
  • 즉, All or Noting의 개념으로서 작업 단위를 일부분만 실행하지 않는다는 것을 의미합니다.

Consistency (일관성)

  • 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지
  • 여기서 말하는 일관성이란, 위의 송금 예제에서 금액의 데이터 타입이 정수형(integer)인데, 갑자기 문자열(string)이 되지 않는 것을 말합니다.
  • 즉, 트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 한다는 뜻입니다.

Isolation (격리성, 고립성)

  • 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리
  • 모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다는 뜻입니다.
  • 실제로 동시에 여러 개의 트랜잭션들이 수행될 때, 각 트랜잭션은 고립(격리) 되어 있어 연속으로 실행되는 것과 동일한 결과를 나타냅니다.
  • 트랜잭션끼리는 서로 간섭할 수 없습니다.

Durability (지속성) 

  • 트랜잭션을 성공적으로 마치면 그 결과가 항상 저장되어야 한다.
  • 성공적으로 수행된 트랜잭션은 영원히 반영이 되어야 하는 것을 말합니다.
  • commit을 하면 현재 상태는 영원히 보장됩니다.

📌 데이터베이스의 격리성 수준


트랜잭션의 특징 ACID 중 I(격리성)의 원칙에 따라 트랜잭션 간에 격리성이 보장되어야 합니다.

하지만 이를 완벽하게 보장하기 위해서는 모든 트랜잭션이 순차적으로 처리 되어야 하고, 이렇게 된다면

성능의 하락으로 이어지게 될 것입니다.

 

트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나

조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것을 말합니다.

 

총 4가지의 격리성 수준이 있으며 이에대해 알아보도록 하겠습니다.

 

READ UNCOMITTED(커밋되지 않은 읽기)

  • 각 트랜잭션에서의 변경 내용이 COMMIT 이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.
  • 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장합니다.
  • DIRTY READ 발생
    • 트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상
    • 트랜잭션 A 가 실행되고 update 됐을 때 그 사이에 트랜잭션 B가 발생한다. 그러면 트랜잭션 A에서 커밋이 되지 않았음에도 불구하고 트랜잭션 B에서 트랜잭션 A가 update 한 내용을 확인할 수 있다.

 

READ COMITTED(커밋된  읽기)

  • 커밋이 된 데이터만 읽습니다.
  • RDB에서 대부분 사용하는 격리 수준 입니다. (오라클이 기본으로 사용하는 격리 수준)
  • Dirty Read와 같은 현상은 발생하지 않지만 Phantom Read 에 더해 NON-REPEATABLE READ 발생
  • NON-REPEATABLE READ(반복 읽기 불가능)
    하나의 트랜잭션 내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REPEATABLE READ 정합성에 어긋나는 것
  • 💡 예시
    트랜잭션 A에서 update 된 내용이 타 트랜잭션에서 바로 보여지지는 않는다. 근데 트랜잭션 A에서 커밋이 완료되었는데 트랜잭션 B에는 아직 완료되지 않은 경우, 트랜잭션 B에서 다시 한번 조회를 하게 된다면 update 된 상태가 조회가 된다
    같은 조회(셀렉트)문인데도 결과가 다르기 때문에 정합성에 어긋난다.
  • 실제 테이블의 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져옵니다.
    • UNDO 영역:간단하게 데이터를 저장하는 버퍼 기능을 한다고 보면 되고, 트랜잭션에서 연산(커밋 롤백)이 이루어지지 않아도 질의문에 의해 수정이 생기면 수정되기 이전 값이 저장되는 영역

 

REPEATABLE READ(반복 가능한 읽기)

  • 자신의 트랜잭션이 생성되기 이전의 트랜잭션에 COMMIT 이 된 데이터만 읽습니다.
  • 어떤  트랜잭션이 읽은 데이터를 다른 트랜잭션이 수정하더라도 동일한 결과를 반환할 것을 보장해줍니다.
  • MySQL 과 MariaDB가 기본으로 사용하는 격리 수준
  • 한 트랜잭션 내에서 동일한 결과를 보장하지만, 새로운 레코드가추가되는 경우에 부정합이 생길 수 있습니다.
  • MySQL 에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 됩니다.
  • PHANTOM READ :
    • 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상
    • MySQL은 갭 락을 통해 거의 발생하지 않는다.

 

SERIALIZABLE(직렬화 가능)

  • 가장 단순한 격리 수준이지만 가장 엄격한 격리 수준 입니다.
  • 데이터를 접근할 때 항상 Lock을 걸고 조회합니다.
  • SERIALIZABLE에서는 Phantom Read 가 발생하지 않습니다.
  • 그러나 성능 문제로 데이터베이스에서는 거의 사용되지 않습니다.

 

📌 데이터베이스의 동시성 과 일관성

격리 수준이 높아지면서 데이터의 일관성이 유지될 수 있지만, 동시에 처리가능한 트랜잭션의 양은 떨어집니다. 격리수준이 낮아지면 일관성은 유지되기 어렵지만, 동시에 처리할 수 있는 트랜잭션의 양은 늘어나게 됩니다.

  • 동시성 : 동시에 수행하는 트랜잭션 양
  • 일관성 : 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것

 

 

 

 

 

출처 :

https://hanamon.kr/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98-acid-%EC%84%B1%EC%A7%88/

https://victorydntmd.tistory.com/129

https://velog.io/@yujiniii/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80

https://mangkyu.tistory.com/299