본문 바로가기

DB

Transaction의 이해

트랜잭션(transaction)은 가장 작은 업무의 단위라고 정의된다. 예를 들어 은행에서 이체하는 경우를 생각하면, 내 계좌에서 10만원의 돈이 출금되고, 그 금액만큼을 다른 사람의 계좌에 입금해야한다. 만일 어떠한 이유에서든지 작업에 문제가 생겨 작업을 되돌려야하는 경우가 있다면, 상대방의 계좌에는 돈이 입금되지 않은 상태에서 그치는 것이 아니라 그 돈이 다시 내 계좌에 존재하도록 하는 상태까지가 원 상태로의 복귀임을 알 수 있다. 즉 이체라는 작업은 내 계좌에서의 출금과 상대방 계좌로의 입금이라는 형태로 구성되어 있다는 것을 알 수 있고, 이것이 가장 작은 업무의 단위임을 알 수 있는 것이다. 그리고 작업은 완전히 돈이 이체되는 것으로 완결되거나(commit), 돈이 이체되지 않고 내 계좌에 돈이 보관되어 있는 초기의 상태로 돌아가야한다는 것(rollback)을 알 수 있다.

 

트랜잭션이 안전하게 수행되기 위한 조건을 ACID라고 하는데 이는 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability)의 약자이다.

 

원자성

모든 트랜잭션은 완전히 실행되거나(all), 아예 실행되지 않아야 한다(nothing). 다시 말해, 진행되다 정지한 트랜잭션은 존재할 수 없다. 이는 트랜잭션이 가장 작은 단위의 업무이기 때문이다. 위에서 든 예시와 같이 이체가 출금만 발생한다던가 입금만 발생하는 경우가 발생해서는 안되는 것이다.

 

일관성

데이터베이스에 트랜잭션을 실행한 후에도 데이터베이스의 일관성은 지켜져야 한다. 즉 정의된 내용에 따라 저장되기에 정당한 데이터만이 데이터베이스에 기록되어야함을 의미한다. 이는 데이터 타입의 일관성, 기본키, 외래키 등의 명시적인 무결성 제약 조건 등을 포함하고 있으며, 위 예시의 계좌 잔고의 합은 이체 전후가 같아야 한다는 사항과 같은 비명시적인 일관성 조건도 포함하고 있다.

 

고립성

고립성은 트랜잭션은 다른 트랜잭션의 영향을 받지 않고 독립적으로 기능이 수행된다는 것을 의미한다. 고립성이 지켜지지 않았을 경우 발생할 수 있는 문제는 Dirty Read, Nonrepeatable Read, Phantom Read 등이 있다.

 

- Dirty Read은 아직 커밋(commit)되지 않은 데이터를 읽는 것으로, 커밋되지 않은 데이터는 롤백(rollback)의 가능성이 있기 때문에 롤백되버린 경우 잘못된 데이터를 사용, 변경하는 문제가 발생할 수 있다.

 

- Nonrepeatable Read는 트랜잭션에서 쿼리를 이용하여 한 행(row)의 데이터를 읽어온 뒤, 다른 트랜잭션이 그 행의 데이터를 수정하거나 삭제한다면 기존 트랜잭션이 다시 그 행의 값을 읽어오는 경우 처음 읽은 값과 다시 읽은 값이 같은 트랜잭션 내에서 서로 다른 값을 갖게 되는 현상을 의미한다. 

 

- Phantom Read는 트랜잭션에서 쿼리를 이용하여 일정 범위의 데이터를 읽어온 경우, 새로운 데이터가 범위 내에 포함되게 추가된 경우, 동일 쿼리를 실행시켰을 때 처음에는 보이지 않던 데이터가 추가되는 경우를 의미한다.

 

고립성을 완전히 보장하기 위해서는 모든 쿼리를 순차적으로 실행해야하지만 이경우 병렬처리가 되지 않기 때문에 성능상 불이익이 크다. 이에 고립화 수준을 나누어 병렬작업을 허용하면서 앞의 문제들을 해결하는 방식을 선택하고 있다. 

 

- Level 0: Read Uncommitted

Level 0는 위 모든 문제를 허용하는 것으로 Dirty Read, Nonrepeatable Read, Phantom Read 등의 모든 문제가 발생할 수 있다.

 

- Level 1: Read Committed

Level 1은 커밋된 데이터만을 읽어오는 것으로 Dirty Read를 방지할 수 있지만, Nonrepeatable Read, Phantom Read은 허용한다.

 

- Level 2: Repeatable Read

Level 2는 한 트랜잭션에서 데이터를 읽은 경우, 해당 데이터에 락(Lock)을 걸어 다른 트랜잭션이 수정, 삭제하지 못하도록 제한하여 트랜잭션 내에서 동일 행의 데이터에 접근할 때 일관성있는 데이터를 가져올 수 있도록 하는 것이다. 이를 이용하면 Nonrepeatable Read는 막을 수 있지만, Phantom Read는 막을 수 없다.

 

- Level 3: Serializable

Level 3은 트랜잭션이 데이터를 읽은 경우, 데이터에 대한 수정, 삭제만을 막는 것이 아니라 새로운 데이터의 삽입도 막기 때문에 Phantom Read까지 방지가 가능하다.

 

고립화 수준에 따라 트랜잭션 간 동시적인 데이터 접근 수준이 바뀌기 때문에 성능과 일관성 수준을 고려하여 선택해야한다. 일반적으로 Read Committed가 기본 고립화 수준으로 많이 쓰이며, mysql은 Repeatable Read를 기본 고립화 수준으로 하고 있다.

 

지속성

지속성은 트랜잭션이 성공적으로 완료되어 커밋되고 나면, 해당 트랜잭션에 의한 모든 변경은 향후에 어떤 소프트웨어나 하드웨어 장애가 발생되더라도 보존되어야 한다.

 

참고

네이버D2: https://d2.naver.com/helloworld/407507

나무위키 - Acid: https://namu.wiki/w/Acid

구루비 DB 스터디: http://wiki.gurubee.net/pages/viewpage.action?pageId=21200923

'DB' 카테고리의 다른 글

MariaDB AES Encrypt, Decrypt  (1) 2021.04.24