[기술 면접] 트랜잭션과 격리성

송진영·2023년 7월 29일
0

기술면접

목록 보기
5/24

트랜잭션(Transaction)

정의

트랜잭션이란 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위라고 할 수 있으며, 트랜잭션에는 여러 개의 연산이 수행될 수 있다.

특징

하나의 트랜잭션은 Commit 되거나 Rollback 된다.

트랜잭션을 사용하는 이유

트랜잭션은 하나의 논리적인 작업의 단위이기 때문에, 여러 개의 작업을 하나의 논리적인 단위로 묶어서 반영과 복구를 조정할 수 있기 위해 사용한다. 따라서, 데이터의 부정합이 일어났을 경우 롤백을 하여 데이터의 부정합을 방지할 수 있다.
Ex. A 계좌에서 출금 -> B 계좌로 입금하는 것을 하나의 논리적인 작업의 단위로 묶어서 반영과 복구를 조정할 수 있다.

ACID

트랜잭션은 4가지의 특징을 가진다. 이를 앞글자만 따서 ACID라고 부른다.

  • 원자성(Atomicity)
    • 트랜잭션은 더 이상 분해가 불가능한 업무의 최소 단위이므로, 전부 처리되거나 아예 하나도 처리되지 않아야 한다.
  • 일관성(Consistency)
    • 일관된 상태의 데이터베이스에서 하나의 트랜잭션을 성공적으로 완료하고 나면 그 데이터베이스는 여전히 일관된 상태여야 한다. 즉, 트랜잭션 실행의 결과로 데이터베이스 상태가 모순되지 않아야 한다.
  • 격리성(Isolation)
    • 실행 중인 트랜잭션의 중간 결과를 다른 트랜잭션이 접근할 수 없다.
  • 영속성(Durability)
    • 트랜잭션이 일단 그 실행을 성공적으로 완료하면 그 결과는 데이터베이스에 영속적으로 저장된다.

트랜잭션 격리성(Transaction Isolation)

트랜잭션에는 일단적으로 접근 레벨이 있으며 DB에 따라 설정이 가능하다. 이런 격리성은 강하게 처리할 수 있으며 반대로 약하게 처리할 수도 있다.

격리성으로 인해 나타날 수 있는 문제점

일반적으로 Dirty Read, Non-Repeatable Read, Phantom Read 3가지이다.

Dirty Read

Dirty Read는 다른 트랜잭션에 의해 수정됐지만 아직 커밋되지 않은 데이터를 읽는 것을 말한다. 아래의 이미지를 보면 Transaction_1이 정상처리되지 않고, Rollback 될 수 있다. 이럴 경우 그 값을 이미 읽은 Transaction_2는 잘못된 값을 가지고 본인의 로직을 처리하는 상태에 놓이게 된다.

Non-Repeatable Read

Non-Repeatable Read는 한 트랜잭션 내에서 같은 Key를 가진 Row를 두 번 읽었는데 그 사이에 값이 변경되거나 삭제되어 결과가 다르게 나타나는 현상이다.

Phantom Read

한 트랜잭션 내에서 같은 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.

※ Phantom Read와 Non-Repeatable Read와의 차이점은 Non-Repeatable Read는 1개의 Row의 데이터의 값이 변경되는 것이며 Phantom Read는 여러 건을 요청하는 것에 대해서 데이터의 값이 변동되는 것이다.

지정할 수 있는 격리성 수준

아래 4개의 격리수준은 ANSI/ISO SQL 표준(SQL92)에서 정의한 내용이다.
위에서 아래로 갈수록 격리 수준이 높아진다.

Read Uncommitted(최하 수준)

  • 가장 낮은 격리 수준으로, 트랜잭션에서 변경된 내용이 커밋되지 않더라도 다른 트랜잭션에서 읽을 수 있다.
  • 이로 인해 'Dirty Read', 'Non-Repeatable Read', 'Phantom Read'와 같은 이상현상이 발생할 수 있다.
  • 데이터 정합성이 보장되지 않고, 동시성이 가장 높다.

Read Committed

  • 이 격리 수준에서는 트랜잭션이 커밋된 데이터만 다른 트랜잭션에서 읽을 수 있다.
  • 'Dirty Read'는 방지할 수 있지만, 'Non-Repeatable Read'와 'Phantom Read'는 여전히 발생할 수 있다.
  • 동시성이 Read Uncommitted보다는 낮아지지만 여전히 높다.

Repeatable Read

  • 이 격리 수준에서는 트랜잭션 내에서 같은 쿼리를 실행하면 항상 동일한 결과가 나온다.
  • 따라서 'Non-Repeatable Read'는 방지할 수 있지만 여전히 'Phantom Read'는 발생할 수 있다.
  • 동시성이 Read Committed보다는 낮아지지만 여전히 중간 정도 수준이다.

Serializable Read(최고 수준)

  • 가장 높은 격리 수준으로, 모든 트랜잭션들이 직렬화되어 실행된다.
  • 따라서 'Dirty Read', 'Non-Repeatable Read', 'Phantom Read' 모두 발생하지 않는다.
  • 하지만 동시성이 가장 낮아진다. 동시에 여러 트랜잭션이 실행될 때 순차적으로 실행되어야 하므로, 성능이 저하될 수 있다.

Q. DB에서 특정 레코드를 조회하는 동안 레코드를 수정하지 못하도록 격리하는 방법

A. Read Committed, Repeatable Read, Serializable 세 가지로 가능하다.

  1. Read Committed :
    Read Committed 격리 수준에서는 트랜잭션에서 변경된 내용이 커밋된 데이터만 다른 트랜잭션에서 읽을 수 있기 때문에 다른 트랜잭션이 아직 커밋되지 않은 변경 사항을 읽을 수 없도록 보장된다. 이를 통해 특정 레코드를 조회하는 동안 해당 레코드를 다른 트랜잭션이 수정하는 것을 방지할 수 있다.
  1. Repeatable Read :
    Repeatable Read 격리 수준은트랜잭션에서 같은 쿼리를 반복 실행할 때 항상 동일한 결과를 보장한다. 따라서 다른 트랜잭션에 의해 해당 레코드가 수정되는 것을 완전히 방지했다. 그렇기 때문에 특정 레코드를 조회하는 동안 해당 레코드를 수정하지 못하도록 격리할 수 있다.
  1. Serializable :
    Serializable 격리 수준은 가장 높은 격리 수준으로, 모든 트랜잭션들이 직렬화되어 실행된다. 즉 동시에 여러 트랜잭션이 실행될 때, 순차적으로 실행되어야 한다. 따라서 다른 트랜잭션에 의해 해당 레코드가 수정되는 것을 완전히 방지할 수 있다.
profile
못하는 건 없다. 단지 그만큼 노력을 안 할 뿐이다.

1개의 댓글

comment-user-thumbnail
2023년 7월 29일

유익한 글이었습니다.

답글 달기