[DB] 트랜잭션 격리수준(isolation level)

개발하는자·2022년 5월 14일
0

DB

목록 보기
2/3

데이터베이스는 일관성을 유지하기 위해 ACID를 따릅니다. 이 네가지 속성( 원자성, 일관성, 독립성, 지속성 ) 중에 독립성(Isolation)은 서로 다른 트랜잭션이 데이터 수정 등으로 서로에게 문제가 발생하지 않도록 서로 격리하는것을 독립성(Isolation), 즉 트랜잭션 격리수준이라고 합니다.




트랜잭션이란?

데이터베이스에서 트랜잭션은 작업 단위를 나타내며 성공시 커밋(Commit), 실패시 롤백(Rollback)을 하여 데이터를 정확하게 관리할 수 있는 기능입니다.




1. ACID

ACID는 데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하기 내용을 가리키는 약어입니다. 짐 그레이가 1970년 말에 정의하였습니다.

  • 원자성(Atomicity)은 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 능력이다. 예를 들어, 자금 이체는 성공할 수도 실패할 수도 있지만 보내는 쪽에서 돈을 빼 오는 작업만 성공하고 받는 쪽에 돈을 넣는 작업을 실패해서는 안된다. 원자성은 이와 같이 중간 단계까지 실행되고 실패하는 일이 없도록 하는 것이다.

  • 일관성(Consistency)은 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것을 의미한다. 무결성 제약이 모든 계좌는 잔고가 있어야 한다면 이를 위반하는 트랜잭션은 중단된다.

  • 독립성(Isolation)은 트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것을 의미한다. 이것은 트랜잭션 밖에 있는 어떤 연산도 중간 단계의 데이터를 볼 수 없음을 의미한다. 은행 관리자는 이체 작업을 하는 도중에 쿼리를 실행하더라도 특정 계좌간 이체하는 양 쪽을 볼 수 없다. 공식적으로 고립성은 트랜잭션 실행내역은 연속적이어야 함을 의미한다. 성능관련 이유로 인해 이 특성은 가장 유연성 있는 제약 조건이다. 자세한 내용은 관련 문서를 참조해야 한다.

  • 지속성(Durability)은 성공적으로 수행된 트랜잭션은 영원히 반영되어야 함을 의미한다. 시스템 문제, DB 일관성 체크 등을 하더라도 유지되어야 함을 의미한다. 전형적으로 모든 트랜잭션은 로그로 남고 시스템 장애 발생 전 상태로 되돌릴 수 있다. 트랜잭션은 로그에 모든 것이 저장된 후에만 commit 상태로 간주될 수 있다.


위 내용은 위키백과에서 ACID를 설명해 놓은 글 입니다. 원자성, 일관성, 독립성, 지속성은 어찌보면 데이터베이스에서 당연히 필요한 기능이라고 볼 수 있습니다.

이 중 독립성(Isolation), 즉 격리수준을 알아보겠습니다.

전제조건을 멀티 스레드 상황으로 설명하겠습니다.





용어 설명

* dirty read : 아직 커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생합니다.

* Non-Repeatable Read : 한 트랜잭션 내에서 같은 쿼리를 두번 조회할 때, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리가 다르게 나타나는 것을 말합니다.

* Phantom Read : 한 트랜잭션 안에서 일정범위의 레코드를 두번 이상 읽을 때, 첫 번재 쿼리에서 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상을 말합니다.





2. 트랜렉션 격리수준

  1. READ UNCOMMITTED
  2. READ COMMITTED
  3. REPEATABLE READ
  4. SERIALIZABLE

위와같이 트랜잭션 격리수준은 네 단계로 나눠져 있습니다.

아래 과정에서 mysql 쿼리로 실습하면서 설명하겠습니다.




간단하게 id, name, age 컬럼이 있는 USER 테이블을 생성했습니다.

임시로 데이터를 넣어줬습니다.




2.1 READ UNCOMMITTED

아직 커밋되지 않은 다른 트랜잭션의 변경사항을 읽을 수 있습니다.

Dirty Read, Non-Repeatable Read, Phantom Read 현상 발생


시작 데이터
1 민수 15
2 영희 15

왼쪽 : T1, 오른쪽 : T2

  1. T1, T2 : set session transaction isolation level read uncommitted;
    트랜잭션 격리 수준을 read uncommitted로 변경합니다.
  2. T2 : start transaction;
    트랜잭션 시작
  3. T1 : start transaction;
    트랜잭션 시작
  4. T1 : upate user set age = 16 where id = 1;
    id 1번 유저의 age를 16으로 변경합니다.
  5. T2 : select * from user;
    유저를 조회합니다.

결과 : 값을 변경한 T1의 commit이 이루어지지 않았음에도 불구하고 T2에서 조회시 변경 값으로 나타납니다. 즉 아직 커밋되지 않은 다른 트랜잭션의 변경사항을 읽을 수 있습니다. 이를 dirty read라고 합니다.

( 가장 낮은 격리 수준 )





2.2 READ COMIITTED

커밋이 되어있는 데이터만을 읽어옵니다.

Non-Repeatable Read, Phantom Read 현상 발생


시작 데이터
1 민수 16
2 영희 15

왼쪽 : T1, 오른쪽 : T2

  1. T1, T2 : set session transaction isolation level read committed;
    트랜잭션 격리 수준을 read committed로 변경합니다.
  2. T2 : start transaction;
    트랜잭션 시작
  3. T1 : start transaction;
    트랜잭션 시작
  4. T1 : upate user set age = 16 where id = 2;
    id 2번 유저의 age를 16으로 변경합니다.
  5. T2: select * from user;
    유저를 조회합니다.

결과 : T1의 트랜잭션 commit이 이루어지지 않았기 때문에 T2에서는 변경 전 값이 나옵니다. 따라서 dirty read를 허용하지 않습니다.







2.3 REPEATABLE READ

다른 트랜잭션이 커밋을 해도 변경 데이터를 읽지 않습니다. ( 완전 격리 )

Phantom Read 현상 발생


시작 데이터
1 민수 16
2 영희 16

왼쪽 : T1, 오른쪽 : T2

  1. T1, T2 : set session transaction isolation level repeatable read;
    트랜잭션 격리 수준을 repeatable read로 변경합니다.
  2. T2 : start transaction;
    트랜잭션 시작
  3. T1 : start transaction;
    트랜잭션 시작
  4. T1 : upate user set age = 20 where id = 1;
    id 2번 유저의 age를 16으로 변경합니다.
  5. T2 : select * from user;
    유저를 조회합니다. ( 값이 바뀌지 않았습니다. )
  6. T1 : commit;
    커밋합니다.
  7. T2 : select * from user;
    유저를 조회합니다. ( 값이 바뀌지 않았습니다. )

결과 : T1의 트랜젝션 commit이 이루어져도 값이 달라지지 않습니다. 따라서 완전히 격리되었다고 볼 수 있습니다.





2.4 SERIALIZABLE

가장 높은 수준의 격리 수준입니다. REPEATABLE READ 와 유사하지만 Phantom Read를 방지합니다. 범위 잠금 기능을 사용하여 테이블에 인덱스가 있으면 WHERE절에 사용된 인덱스 범위(예: ID 1 ~ 3 사이)에 따라 레코드를 잠급니다. 테이블에 인덱스가 없으면 전체 테이블을 잠급니다.






참고 링크

https://www.geeksforgeeks.org/transaction-isolation-levels-dbms/

http://wiki.gurubee.net/pages/viewpage.action?pageId=21200923

profile
To the moon.

0개의 댓글