동시성 제어가 뭔데?
동시성 제어(Concurrency Control)이란, 동시에 실행되는 트랜잭션 수를 최대화하면서도 입력, 수정, 삭제, 검색 시 데이터 무결성이 유지될 수 있도록 노력하는것을 말한다.
여러 개의 트랜잭션이 동시에 수행될 때, 데이터베이스 애플리케이션은 이들 트랜잭션이 서로 간섭을 일으키는 현상을 최소화시키면서 데이터의 일관성과 무결성을 보장하도록 해야 한다.

동시성(Concurrency)
다중 사용자가 같은 데이터를 동시에 액세스
일관성(Consistency)
자신이 발생시킨 변경 사항과 다른 트랜잭션의 변경 사항을 포함해 일관성있는 상태로 데이터를 바꿈
그런데 왜 동시성 제어가 왜 어려울까?
동시성 제어가 어려운 이유는 위의 그래프를 보는 것과 같이 동시성과 일관성을 트레이드 오프 관계이기 때문이다.
즉, 동시성을 높이려고 Lock의 사용을 최소화하면 읽기 일관성을 유지하기 어렵고, 데이터의 일관성을 높이려고 Lock을 많이 사용하면 동시성이 떨어지게 된다.
따라서 동시성과 일관성을 함께 제어하려면 매우 세심한 주의가 필요하다.
트랜잭션이 무엇일까?
트랜잭션(Transaction)이란 여러 개의 수정작업이나 하나의 작업처럼 전부 처리되거나 아예 전부 처리가 안 되도록 하는 일련의 최소 단위를 말한다. 전부 처리되면 커밋, 하나라도 실패하면 롤백한다.
트랜잭션의 특징은?
트랜잭션은 데이터베이스 갱신과 관련하여 4가지 중요한 특징(ACID)을 갖는다
더 이상 분해가 불가능한 업무의 최소 단위를 말한다.
트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환한다. 즉 트랜잭션 실행의 결과로 데이터베이스 상태가 모순되지 않는다.
트랜잭션이 실행 중에 생성하는 연산의 중간 결과는 다른 트랜잭션이 접근할 수 없다.
트랜잭션이 일단 그 실행을 성공적으로 완료하면 그 결과는 데이터베이스에 영속적으로 저장된다.
트랜잭션 수준 읽기 일관성이 뭔데?
트랜잭션 수준 읽기 일관성(Trasaction-Level Read Consistency)은 트랜잭션이 시작된 시점을 기준으로 일관성 있게 데이터를 읽어들이는 것을 말한다. 트랜잭션이 진행되는 동안 다른 트랜잭션에 의해 변경사항이 발생하더라도 이를 무시하고 계속해서 일관성있는 데이터를 유지한다.
오라클은 완벽한 문장 수준 읽기 일관성을 보장하지만, 트랜잭션에 대해서는 기본적으로 보장하지 않는다. 다른 DBMS도 마찬가지다.
트랜잭션 수준으로 읽기 일관성을 강화하려면 트랜잭션 고립화 수준을 높여 주어야 한다.
트랜잭션 고립화 수준이 뭐죠?
SQL 표준 ANSI에서 정의하고 있는 네 가지 트랜잭션 고립화 수준으로 나눌 수 있다
트랜잭션에서 처리 중인, 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다
Dirty Read, Non-Repeatable Read, Phantom Read 현상 발생
오라클은 레벨 0은 지원하지 않음
트랜잭션이 커밋되어 확정된 데이터만 읽는 것을 허용
대부분의 DBMS의 Default Level로 채택중인 일관성 모드
Non-Repeatable Read, Phantom Read 현상 발생
DB2, SQL Server, Sybase의 경우 읽기 공유 Lock을 이용해서 구현
하나의 레코드 읽을 때 Lock 설정, 해당 레코드를 나가는 순간 Lock 해제
Oracle은 Lock을 사용하지 않고 쿼리시작 시점의 Undo 데이터를 제공하는 방식으로 구현
선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신하거나 삭제하는 것을 불허함으로써 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴
Phantom Read 현상 발생
DB2, SQL Server, Sybase의 경우 읽은 데이터에 걸린 공유 Lock을 커밋할 때까지 유지하는 방식으로 구현
Oracle은 레벨 2를 명시적으로 지원하지 않지만 FOR UPDATE 절을 이용해 구현 가능
선행 트랜잭션이 읽은 데이터를 후행 트랜잭션이 갱신하거나 삭제하지 못할 뿐만 아니라 중간에 새로운 레코드를 삽입하는 것도 막아줌
완벽한 읽기 일관성 모드를 제공
트랜잭션 수준의 읽기 일관성 모드까지 제공
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;각 쿼리로 트랜잭션 고립화 수준을 조정해주면 된다
Dirty Read가 언제 발생하죠?
Dirty Read란 아직 커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생한다. 만약 Dirty Read를 허용하는 상황에서 쿼리 수행 도중에 다른 트랜잭션에 의해 특정 값이 변경된다면 쿼리의 최종 결과 값이 비일관성 상태에 놓이게 될 수 있다. 왜나면, 그 트랜잭션이 어떤 이유에서건 롤백될 수 있기 때문이다.
하지만 대부분 DBMS의 트랜잭션 고립화 수준은 레벨 1로 설정하기 때문에 Dirty Read는 발생하지 않음. 즉, 커밋된 데이터만 읽을 수 있도록 허용한다
Non-Repeatable Read가 뭔데?
한 트랜잭션 내에서 같은 쿼리가 두 번 수행할 때, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리의 결과가 상이하게 나타나는 비일관성이 발생하는 것을 말한다.
Phantom Read란?
한 트랜잭션 안에서 일정범위의 레코드들을 두 번 이상 읽을 때, 첫 번째 쿼리에서 없던 유령 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.

트랜잭션 고립화 수준을 높이면 일관성이 향상되지만, 더 넓은 범위의 Lock을 더 오랫동안 유지하는 방식을 사용하므로 동시성은 저하된다.
하지만 오라클은 트랜잭션 고립화 수준을 높이더라도 Lock을 사용하지 않아 동시성이 저하되지 않는다.
-> 오라클은 Undo 데이터를 활용함으로써 높은 수준의 동시성과 읽기 일관성을 유지하는 대신 다른 DBMS에는 없는 Snapshot too old(ORA-01555)를 던짐
고생해따!!