병행 제어
DBMS는 여러 사용자가 동시에 데이터베이스를 이용할 수 있도록 병행 수행 기능을 제공한다. 병행 수행은 실제로 여러 트랜잭션이 차례로 번갈아 수행되는 인터리빙(interleaving) 방식으로 지원한다. 하지만 아무런 제어 없이 병행 수행을 할 경우 갱신 분실, 모순성, 연쇄 복귀 등의 문제가 발생할 수 있다. 때문에 트랜잭션을 병행 수행 하면서도 정확한 수행 결과를 얻을 수 있도록 트랜잭션의 병행 수행을 제어하는 병행 제어(동시성 제어)가 필요하다.
병행 제어 기법
병행 제어의 핵심 목표는 트랜잭션을 번갈아 가면서 수행하면서도 트랜잭션을 순차적으로 실행하는 것과 같은 결과를 내는 것이다. 트랜잭션을 순차적으로 실행한 결과는 항상 정확하고 일관되기 때문이다. 가장 많이 사용하는 병행 제어 기법으로 로킹 기법을 많이 사용한다.
로킹(locking) 기법은 병행 수행 되는 트랜잭션들이 동일한 데이터에 동시 접근되지 못하도록 lock과 unlock이라는 2개의 연산을 이용해 제어하는 기법이다. lock을 통해 데이터의 독점권을 가져오고 unlock를 통해 독점권을 반납한다. 한 트랜잭션이 데이터를 독점적으로 사용함으로써 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 상호 배제(mutual exclusion)한다. 이러한 방식은 OS에서 공유 자원에 대한 스레드 동기화에 사용되는 뮤텍스와 세마포어의 방식과 매우 유사하다.
로킹 규약
로킹 기법을 사용하려면 모든 트랜잭션이 로킹 규약을 지켜야한다. 로킹 규약이란 트랜잭션이 데이터에 접근하기 전에 먼저 해당 데이터에 lock 연산을 실행해 독점권을 얻어야 한다는 규약이다. 데이터베이스에서 데이터에 접근하기 위한 연산은 read와 write이므로 이들 연산을 실행하기 전에 반드시 lock 연산을 실행해야 한다. lock 연산을 실행한 트랜잭션 만이 unlock 연산을 실행해 독점권을 반납할 수 있다. 데이터에 write 연산을 수행하기 전에는 반드시 한 트랜잭션만이 해당 데이터에 독점권을 가져야한다. 하지만 read 연산은 그렇지 않다. 여러 트랜잭션이 동시에 같은 데이터에 read 연산을 수행해도 문제가 발생하지 않는다. 데이터베이스는 write 연산에 비해 read 연산의 비중이 대략 90%를 차지한다. 따라서 여러 트랜잭션이 동시에 수행해도 상관없는 read 연산을 한 트랜잭션만이 독점권을 얻어 실행한다면 병행성과 처리 성능이 매우 떨어진다. 그래서 lock 연산을 아래와 같이 두 종류로 구분한다.
공용(shared) lock
- 트랜잭션이 A 데이터에 공용 lock 연산을 실행하면, 해당 데이터에 read 연산을 실행할 수 있지만 write 연산은 실행할 수 없다.
- A 데이터에 공용 lock을 걸어도 다른 트랜잭션은 A 데이터에 공용 lock 연산을 실행할 수 있다.
- A 데이터에 공용 lock이 하나라도 걸려있다면 전용 lock 연산을 실행할 수 없다.
전용(exclusive) lock
- 트랜잭션이 A 데이터에 전용 lock 연산을 실행하면 A 데이터에 read 연산과 write 연산을 모두 실행할 수 있다.
- A 데이터에 전용 lock을 걸면 다른 트랜잭션은 A 데이터에 공용, 전용 lock 연산을 실행할 수 없다.
read 연산 실행 전에는 공용 lock을 write 연산 실행 전에는 전용 lock을 실행하면 병행성과 처리 성능을 올릴 수 있다. 하지만 로킹 규약만으로 병행 수행의 문제점을 온전히 해결할 수 없다. 따라서 2단계 로킹 규약(2 phase locking protocol)이 등장하게 되었다.
2단계 로킹 규약
모든 트랜잭션이 2단계 로킹 규약을 준수하면 트랜잭션을 병행 수행해도 트랜잭션을 순차적으로 수행한 것과 같은 결과를 낼 수 있다. 2단계 로킹 규약은 기본 로킹 규약에 더불어 lock과 unlock 연산을 2단계로 나누어 실행하는 규약이다.
- 확장 단계 : 트랜잭션이 lock 연산만 실행할 수 있고 unlock 연산은 실행할 수 없는 단계
- 축소 단계 : 트랜잭션이 unlock 연산만 실행할 수 있고 lock 연산은 실행할 수 없는 단계
트랜잭션이 처음에 실행하면 확장 단계로 들어가 lock 연산만 실행할 수 있다. 그러다가 unlock 연산을 수행하면 축소 단계로 들어가 그때부터는 unlock 연산만 실행할 수 있게 된다. 따라서 unlock 연산을 수행하기 전에 필요한 모든 lock 연산을 실행해야 한다.
교착 상태
2단계 로킹 규약을 적용하면 트랜잭션을 병행 수행해도 트랜잭션을 순차적으로 수행한 것과 같은 결과를 낼 수 있지만 교착 상태가 발생할 수 있다. 교착 상태란 상대가 독점하고 있는 데이터에 unlock 연산이 실행되기를 서로 기다리면서 트랜잭션의 수행이 중단된 상태이다. 교착 상태에 빠진 트랜잭션들은 수행되지 못하고 상대방이 unlock 연산을 실행해주기를 한없이 기다리게 된다. 교착 상태는 처음부터 발생하지 않도록 예방하거나, 발생했을 때 빨리 탐지하여 필요한 조치를 취하는 방법으로 해결한다.
로킹 단위
lock 연산을 실행하는 대상 데이터의 크기인 로킹 단위도 생각해야한다. lock 연산은 크게 전체 데이터베이스부터 작게는 속성에 이르기까지 다양한 크기의 데이터를 대상으로 실행할 수 있다. 이때 로킹 단위가 클수록 병행 제어가 쉽지만 병행성은 낮아지고 로킹 단위가 작을수록 병행 제어는 어렵지만 병행성은 높아진다. 그러므로 시스템에 따라 적절한 로킹 단위를 선택하는 것이 중요하다.
'Computer Science > DataBase' 카테고리의 다른 글
Mysql 서브 쿼리 (0) | 2023.11.16 |
---|---|
MySQL Join (0) | 2023.11.16 |
[데이터베이스 - 8] 장애와 회복 (0) | 2022.10.12 |
[데이터베이스 - 7] 트랜잭션 (0) | 2022.10.11 |
[데이터베이스 - 6] SQL (0) | 2022.09.29 |