transaction은 데이터에 접근하거나 데이터를 수정하는, 가장 작은 프로그램 실행 단위를 말한다. sql문들을 마구잡이로 실행하지 않고, transaction을 고려해야하는 이유는 크게 두 가지로 나눌 수 있다.
데이터의 통합성을 위해서, 모든 operations는 다음의 조건을 충족해야한다.
Atomicity
: transaction 내의 모든 동작은 데이터에 완전히 반영되거나, 아예 반영되지 않아야한다. Consistency
: 실행되는 transaction은 데이터베이스와 일관성을 유지해야한다.Isolation
: 여러 개의 transaction이 동시에 실행되더라도, 이들은 서로의 동시적인 실행을 몰라야한다. transaction 실행 중간의 결과들은 다른 동시에 실행되는 transaction에게는 숨겨져야한다. Duarbility
: transaction이 성공적으로 완료되고 나서는, 데이터베이스에 영속되어야한다. transactions의 동시적인 실행이 ACID를 해칠 수 있음에도, 매우 큰 장점을 가지고 있다.
그래서 RDBMS들은 이러한 장점과 데이터베이스의 일관성이 양립할 수 있는 방법을 만들었다. isolation을 유지하기 위한 mechanisms를 사용해서, 데이터베이스의 일관성을 해치지 않으면서 동시적인 실행이 가능하게 한다.
이를 위한 RDBMS들의 해결책들과, 관련된 개념에는 무엇이 있는지 알아봤다.
Schedules는 동시에 실행되는 transaction의 instructions 실행 순서를 말한다. 성공적으로 실행된 transaction은, 마지막 statement로 commit을 가질 것이고, 도중에 실패한 transaction은 abort instruction을 실행해야한다.
다음의 세 schedule은 serial 여부와 consistency의 관계를 보여준다.
첫 번째 예시는 serial하고, 두 번째 예시는 serial하지 않지만, consistency가 유지된다. 반면 세 번째 예시는 not serial하면서 inconsist한 경우이다.
즉, serial하지 않으면서 (동시에 여러 transaction이 실행되면서)도 일관성, isolation을 유지할 수 있는 것이다. 이것을 결정하는 개념이 바로 serializability이다.
serial schedule과 같은 결과를 만드는 schedule을 serializable하다고 말한다. 기본적인 가정은, 모든 transaction이 데이터베이스의 일관성을 해치지 않도록 하는 것이다.
두 개의 transaction(Ti, Tj)이 동시에 실행되고, 이 transactions는 둘 다 같은 아이템 Q에 접근하는 instructions(Li, Lj)를 포함하고 있다고 하자. 이 경우에서 conflict가 발생하는 경우는 다음과 같다.
일관성에 문제가 생긴다는 것을 직관적으로도 알 수 있다. 중요한 것은 같은 자원에 동시에 접근하는데, 이 상황에서 write/update가 발생하는 지이다. 동시에 Q에 접근하지 않거나, write가 아닌 read만 발생한다면, 문제가 없다.
위와 같이 conflict의 관점에서의 serializability를 conflict serializability
라고 한다. 특정한 schedule S 내부의 non-conflicting한 instructions들을 순서를 바꿔서 표현할 수 있다. 이 경우에 두 schedule은 conflict equivalent
하다. 그리고 S가 serial schedule에 대해서 conflict equivalent
하다면, conflict serializable
하다. 즉, conflict serializable하다면, 직렬화 가능한 schedule이라는 말이다.
예시와 함께 개념을 확인해보자.
conflict equivalent
하다.conflict serializable
하다.반면에 위와 같은 예시는 순서를 바꿀 수 조차 없다. (=conflict equivalent
schedule을 만들 수 없다.) 따라서 conflict serializable
할 수도 없다.
schedule이 failure이 발생한 이후에 일관성이 있는 상태로 회복될 수 있다면, recoverable schedule
이다. 특정한 transaction에 대해서, 이 transaction이 접근한 데이터를 먼저 수정한 transaction들이commit되고 나서 commit하는 경우에만 recoverable하다. 다른 말로 하면, Tj가 Ti에 의해서 수정된 데이터를 읽고 있다고 할 때, Ti의 commit이 Tj의 commit보다 선행되어야한다는 말이다.
recoverable하지 않은 schedules는 다음과 같은 문제를 일으킨다.
왼쪽의 예시를 보면, T9는 recoverable하지 않다. T8의 commit 이전에 commit되었기 때문이다. 이 경우에 T8의 실행의 atomicity는 보장되지 않는다. 또한 T9는 durability가 위반된 상태를 만들었다.
즉, T8이 abort해야하는 상황이 되는 순간, T9는 inconsistent한 데이터에 접근한 셈이다.
이와 같은 문제들이 발생할 수 있기 때문에 데이터베이스는 recoverable한 schedule을 보장해야한다.
이번에는 isolation과 관련된, 가능한 문제들에 대해서 알아보자.
다음의 세 가지 문제는 같은 데이터에 동시에 접근하는 transaction들 사이의 고립성이 보장되지 않은 상황이라는 것을 직관적으로 알 수 있다.
이러한 문제들을 조정하기 위해서 SQL 표준에서는 isolation level을 정의했다.
Serializable
Repeatable read
Read committed
Read uncommitted
dirty read | non-repeatable read | phantoms | |
---|---|---|---|
read uncommited | y | y | y |
read committed | n | y | y |
repeatable read | n | n | y |
serializable | n | n | n |
데이터베이스의 정합성을 위해서는 당연히 serializable해야할 것이지만, 효율성이나 다른 많은 측면을 고려했을 때 다른 level을 사용하게 될 수도 있다.
예를 들어, 대략적인 통계 데이터만을 찾는 task 처럼 말이다. 필요에 따라서 적절하게 설정하는 것이 좋다.
출처 - Database System Concepts, 7thEd. ©Silberschatz, Korthand Sudarshan