3. 데이터베이스
Transaction
데이터베이스에서 수행되는 여러 작업을 하나의 논리적 단위로 수행하는 것
데이터베이스를 많은 사용자가 동시에 접근한다.
동시성 제어를 통해 다수 사용자가 동시에 접근하도록 허용하면서 데이터베이스의 일관성을 유지하도록 한다.
트랜잭션을 실행하는 도중에 시스템이 고장 나도 데이터베이스의 일관성을 유지한다.
일관성이란?
데이터베이스를 구성할 때에 정해놓은 규칙들은 트랜잭션을 성공하고 나서도 계속해서 유지되어야 한다.
만약 쿼리 실행 도중에 멈춘다면, 일관성이 깨졌다고 표현한다.
DBMS는 트랜잭션 단위로 작업을 관리하고, 동시성 제어, 장애 발생 시로부터 회복하는 기능이 핵심이라 할 수 있다.
예시
전체 사원의 급여를 6% 인상하려고 한다.
UPDATE EMPLOYEE
SET SALARY = SALARY * 1.06;
이 때, DBMS는 전체 사원의 급여가 인상되거나 어떤 사원도 인상되지 않도록 보장해야한다.
만약, 중간에 시스템이 다운되면 DBMS는 어떻게 대응해야 할까? DBMS는 정보를 중복으로 저장해서 대응한다.
트랜잭션의 특성
ACID, 데이터베이스의 무결성과 일관성이 보장되기 위해서 네 가지 특성을 만족해야한다.
Atomicity, all or nothing
한 트랜잭션 내의 모든 연산들이 완전히 수행되거나 전혀 수행되지 않는다.
Consistency
트랜잭션 중간에는 일관성이 깨질 수 있지만
트랜잭션 전, 후로는 일관성이 유지됨을 보장해야 한다.
Isolation
한 트랜잭션이 데이터를 갱신하는 동안 이 트랜잭션이 완료되기 전에는
갱신 중인 데이터를 다른 트랜잭션들이 접근하지 못하도록 해야 한다.
다만, 격리 수준에 따라 의도적으로 Isolation을 어기기도 한다.
다수의 트랜잭션들이 동시에 수행되더라도
그 결과는 어떤 순서에 따라 트랜잭션들을 하나씩 차례대로 수행한 결과와 같아야 한다.
Durability
한 트랜잭션이 완료되면 갱신한 데이터를 시스템 고장이 나도 손실하지 않도록 보장한다.
트랜잭션의 연산
- 시작, start
- 완료, commit
- 취소, rollback
트랜잭션의 상태
Partially commited
트랜잭션의 마지막 연산이 실행된 직후를 부분 완료(partially committed) 상태라고 한다.
아직 데이터베이스에 반영하지 않은 상태이다.
Committed
commit 연산을 실행한 상태이다.
Aborted
트랜잭션 수행에 실패하여 rollback 연산을 실행한 상태이다.
Aborted 상태가 되면 모든 연산을 취소하고 트랜잭션이 수행되기 전의 상태로 되돌린다.
외부의 문제로 트랜잭션이 종료되었다면 트랜잭션을 다시 시작하지만,
트랜잭션이 논리적 오류를 포함하거나 데이터베이스에 없는 데이터에 접근하려하면 트랜잭션을 폐기한다.
데이터의 이동
- input: 데이터베이스에서 주기억 장치 버퍼로 가져오는 행위
- output: 주기억 장치 버퍼에서 데이터베이스로 저장하는 행위
- read: 주기억 장치 버퍼에서 응용 프로그램로 데이터를 읽는 행위
- write: 응용 프로그램에서 주기억 장치 버퍼로 데이터를 쓰는 행위
회복
데이터베이스에 장애가 발생했을 때, 발생 전의 일관된 상태로 복구시키는 것
회복 원리
DB 회복의 원리는 데이터를 중복으로 저장하는 것이다.
저장 방식은 다음의 두 가지가 있다.
- dump: 데이터베이스 전체를 다른 저장 장치에 주기적으로 복사하는 방법
- 로그: 연산이 실행될 때마다 데이터 변경 전과 이후의 값을 기록하는 방법
로그 레코드 종류
변경 이전의 값과 이후의 값을 기록한 로그는 레코드 단위로 기록된다.
회복 연산
redo
가장 최근에 저장한 데이터베이스 복사본을 가져온 후
로그를 이용해 복사본이 만들어진 이후에 실행된 모든 변경 연산을 재실행하여 발생하기 직전의 상태로 복구
undo
로그를 이용해 지금까지 실행된 모든 변경 연산을 취소하여 데이터베이스를 원래의 상태로 복구
회복 기법
즉시 갱신 회복 기법
트랜잭션 수행 중에 데이터를 변경한 연산의 결과를 데이터베이스에 즉시 반영한다.
정상적으로 회복이 작동하기 위해서는 로그 파일을 먼저 기록 후, 데이터베이스에 연산을 반영한다.
장애 발생 시점에 따라 undo와 redo 연산을 구분하여 회복한다.
트랜잭션이 완료되기 전에 장애가 발생한 경우
즉, 로그에 start는 있지만 commit이 없는 경우에는 undo 연산을 실행한다.
start도 있고 commit도 있는 경우에는 redo를 통해 회복한다.
지연 갱신 회복 기법
트랜잭션이 수행되는 동안에 데이터 변경 연산의 결과를 로그 파일에만 기록해주었다가
부분 완료된 후에 로그에 기록된 내용으로 데이터베이스에 반영한다.
commit 이전에 장애가 발생했다면 로그 버리면 되고 commit까지 진행했다면 redo 한다.
검사 시점 회복 기법
즉시 갱신 회복 기법과 지연 갱신 회복 기법은 로그를 사용해서 회복하는 기법이다.
로그 전체를 대상으로 회복을 진행하면 회복에 많은 시간이 소요되고 불필요한 연산을 반복해야 한다.
검사 시점 회복 기법은 위 두 방법을 사용하되, 일정 시간 간격으로 checkpoint를 만들어 회복 시간을 단축한다.
동시성 제어
많은 사용자가 동시에 공유 자원에 접근하면 생기는 문제를 알아보고 동시성 제어를 위한 규약을 알아본다.
공유 자원에 많은 사용자가 접근하면 생기는 문제
- dirty read: 완료되지 않은 트랜잭션의 갱신한 데이터를 읽는 것
- uprepeatable read: 한 트랜잭션이 동일한 데이터를 읽을 때, 다른 값을 읽는 것
- phantom read: 트랜젝션에서 현재 조회하고 있는 데이터에 대해서만 lock을 하면 추가된 데이터는 lock이 아니므로 insert 전후 조회값이 다를 수 있다.
lost update
수행 중인 트랜잭션이 다른 트랜잭션을 덮어 씀으로써 무효가 되는 것
cascade rollback
dirty read를 통해 읽은 데이터가 rollback하게 되면 연쇄적으로 rollback이 발생할 수 있다.
또는, commit 되지 않은 데이터를 읽고 사용한 뒤에 commit을 한 경우에는 되돌릴 수 없으므로 commit 하지 않고 대기해야 하는 문제가 있다.
문제의 예시
dirty read
트랜잭션 T1에서 A 사용자의 십 만원을 인출한 후에 T2에서 모든 사용자의 잔액 평균값을 조회했다.
이후 T1이 rollback되면서 A의 잔액이 원래대로 돌아간다면 T2에서 조회한 평균값은 잘못된 데이터를 조회한 것이 된다.
lost update
트랜잭션 T1에서 특정 데이터 X를 읽고 난 후 5를 더하는 연산을 하고, T2에서 X를 읽고 5를 빼는 연산을 한 후에 저장을 하면
X+5가 저장되거나 X-5가 저장될 수 있다. 정상적인 동작은 X가 원래의 값을 가지고 있어야한다.
uprepeatable read
dirty read의 예에 이어서, T1이 rollback된 이후에 T2에서 다시 평균값을 조회한다면 다른 평균값을 얻게 된다.
serializable
여러 트랜잭션들을 동시에 수행하지만 차례대로 수행한 것과 같은 결과를 갖도록 한다
트랜잭션 스케쥴
트랜잭션이 동시에 수행될 때, 여러 트랜잭션이 번갈아가며 실행되는 방식을 interleaving 라고 한다.
직렬 스케쥴
인터리빙 방식을 사용하지 않고 트랜잭션을 순차적으로 실행시키는 것
항상 정확한 결과를 얻지만 동시에 수행할 수 없으므로 사용되지 않는다.
비직렬 스케쥴
인터리빙 방식을 이용한다.
serializable, 직렬 가능 스케쥴
인터리빙 방식을 이용하지만 직렬 스케쥴와 같은 결과를 갖는 스케쥴을 의미한다.
동시성 제어 기법에서 가장 많이 사용하는 lock 기법에 대해 알아보자.
Locking
한 트랜잭션이 먼저 접근한 데이터에 대해 연산을 모두 마칠 때까지,
다른 트랜잭션이 접근하지 못하도록 상호 배제(mutual exclusion)한다.
locking 단위는 데이터베이스부터 column까지 넓게 이루어질 수 있다.
단위가 커질수록 병행성은 낮아지지만 제어가 쉽고,
작아질수록 제어가 어렵지만 병행성은 높아지는 특징이 있다.
시스템에 따라 적절한 단위를 선택해야 한다.
Lock 연산
처리 효율성을 높이기 위해 다음의 lock 연산을 둔다.
- shared lock: read 연산만을 수행하여 다른 트랜잭션도 동시에 shared lock할 수 있다.
- exclusive lock: read와 write 연산을 할 수 있지만 다른 트랜잭션은 shared, exclusive lock 연산을 수행할 수 없다.
하지만 여전히 트랜잭션의 serializable을 보장할 수 없다.
2-phase locking protocol
serializable을 보장하기 위해 추가된 규약이다.
2단계 잠금은 다음 두 단계로 구성된다. 아래의 lock 포인트 그림과 함께 이해해보자.
확장(Growing) 단계
트랜잭션이 데이터베이스의 자원을 요청할 때 잠금을 획득한다. 획득된 잠금은 트랜잭션이 완료될 때까지 유지된다.
위 전략에서 lock 연산만 실행할 수 있다는 것은 아래 그림처럼 중간에 unlock하지 않고 자원에 대해 lock만 한다는 것을 의미한다.
축소(Shrinking) 단계
트랜잭션이 모든 데이터 조작을 마치고 커밋하거나 롤백할 때 잠금을 해제한다.
커밋되면 트랜잭션에서 획득한 모든 잠금이 해제되고 다른 트랜잭션들이 해당 자원에 대해 잠금을 획득할 수 있게 된다.
롤백되면 트랜잭션에서 획득한 모든 잠금이 즉시 해제된다.
lock 포인트
한 트랜잭션에서 필요로 하는 모든 lock를 걸어놓은 시점
교착 상태, deadlock
2PL(2 phase lock)에서는 데드록이 발생할 수 있다.
두 개 이상의 트랜잭션들이 서로 상대방이 보유하고 있는 lock을 기다리고 있는 상태를 말한다.
데드록을 탐지하는 알고리즘으로 데드록을 식별하고 희생자를 선정하여 풀 수 있다.
출처
기술 면접 대비 cs전공 핵심 요약집 - 길벗
https://youtu.be/bLLarZTrebU?si=8ulQNZ4xwF6d-5l0
https://youtu.be/taUeIi6a6hk?si=9FHgc1YhbWwo-Cy2
'컴퓨터과학' 카테고리의 다른 글
[운영체제] 페이징 (1) (1) | 2024.03.16 |
---|---|
[운영체제] 물리 메모리 관리 (0) | 2024.03.16 |
[전공 복습] 2. 네트워크 (1) | 2024.03.13 |
[전공 복습] 1-2. 운영체제 (1) | 2024.03.13 |
[전공 복습] 1-1. 운영체제 (1) | 2024.03.13 |