[DATABASE] 데이터베이스 개론_CH10

bin1225·2024년 10월 29일
0

DATABASE

목록 보기
15/19
post-thumbnail

데이터베이스 개론2판(김연희)를 읽고 복습목적으로 내용을 정리한 글입니다.

1. 트랜잭션(transaction)

1.1 트랜잭션이란

트랙잭션은 하나의 작업을 수행하는 데 필요한 데이터베이스의 연산들을 모아놓은 것으로, 데이터베이스에서 논리적인 작업의 단위가 된다.

트랜잭션의 예를 들어보자,

인터넷 뱅킹을 통해 계좌이체를 하는 과정에서 입금과 출금 작업이 필요하다.
만약 둘 중 한 작업만 성공하고 나머지 작업을 수행되지 않는다면, 돈의 총량이 증가하거나 감소하는 모순된 상황이 발생한다.

따라서 둘 중 하나라도 처리 과정에서 오류가 발생하면 모든 명령문의 실행을 취소하고 트랜잭션 작업 전 상태로 되돌아가야 한다.

1.2 트랜잭션의 특성

트랜잭션이 성공적으로 처리되어 데이터베이스의 무결성과 일관성이 보장되려면 4가지 특성을 만족해야 한다.

ACID 특성

  • 원자성(atomicity)
  • 일관성(consistency)
  • 격리성(isolation)
  • 지속성(durability)

1.2.1 원자성(atomicity)

트랜잭션을 구성하는 연산들이 모두 정상적으로 실행되거나 하나도 실행되지 않아야 한다는 all-or-nothing 방식을 의미한다.

원자성을 보장하면 트랜잭션을 구성하는 연산 중 일부만 처리한 결과를 데이터베이스에 반영하는 일이 없게 된다.

원자성을 보장하려면 장애가 발생했을 때 데이터베이스의 원래 상태로 복구하는 회복 기능이 필요하다.

1.2.2 일관성(consistency)

트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관된 상태를 유지해야 함을 의미한다.

트랜잭션을 수행하는 과정에서 일시적으로 일관적이지 않을 수 있지만, 실행이 완료된 후에는 일관된 상태를 유지해야 한다.

예를 들어, 계좌이체 과정에서 계좌이체 전,후 돈의 총량이 같아야 한다.

1.2.3 격리성(isolation)

격리성은 고립성이라고도 하는데, 현재 수행 중인 트랜잭션이 완료될 때까지 트랜잭션이 생성한 중간 연산 결과에 다른 트랜잭션들이 접근할 수 없음을 의미한다.

트랜잭션 실행 과정에서 생기는 중간 결과에 다른 연산이 관여하게 된다면 모순된 데이터를 변경해 잔액을 정확히 예측하기 어려워 데이터베이스의 일관성을 보장할 수 없다.

OS에서 racecondition이 발생하는 원리와 비슷한 것 같다.

따라서 중간결과에 접근을 금지하여 트랜잭션의 격리성을 보장한다.

1.2.4 지속성(durability)

지속성은 영속성이라고도 하는데, 트랜잭션이 성공적으로 완료된 후 데이터베이스에 반영한 수행 결과는 어떠한 경우에도 손실되지 않고 영구적이어야 함을 의미한다.

시스템에 장애가 발생하더라도 트랜잭션 작업 결과는 없어지지 않고 그대로 남아있어야 한다.

이를 위해 시스템 장애 발생 시 데이터베이스를 원래 상태로 복구하는 회복 기능이 필요하다.

트랜잭션의 특성을 지원하는 DBMS의 기능

1.3 트랜잭션의 연산

트랜잭션 수행 관련 주요 연산에는 작업 완료를 의미하는 commit연산과 작업 취소를 의미하는 rollback연산이 있다.

  • commit: 트랜잭션이 성공적으로 수행되었음을 선언 (작업완료)
  • rollback: 트랜잭션을 수행하는 데 실패했음을 선언 (작업 취소)

1.4 트랜잭션의 상태

트랜잭션은 다음의 5가지 상태 중 하나에 속하게 된다.

활동 상태(active)

트랜잭션이 수행되기 시작하여 현재 수행중인 상태이다.

부분 완료 상태(partially committed)

트랜잭션의 모든 연산의 처리가 끝났지만 아직 최종결과를 데이터베이스에 반영하지 않은 상태이다.

완료 상태(committed)

트랜잭션이 성공적으로 완료되어 commit연산을 실행한 상태이다.
트랜잭션을 종료한다.

실패 상태(failed)

하드웨어, 스프트웨어, 트랜잭션 내부 오류 등 여러 이유로 장애가 발생하여 트랜잭션의 수행이 중단된 상태이다.

철회 상태(aborted)

트랜잭션 수행이 실패하여 rollback연산을 실행한 상태이다.
트랜잭션이 수행되기 전의 데이터베이스 상태로 돌아가면 트랜잭션을 종료한다.

  • 하드웨어나 소프트웨어 이상인 경우 철회된 트랜잭션을 다시 시작한다.
  • 데이터가 존재하지 않거나 트랜잭션의 논리적인 오류가 원인인 경우 철회된 트랜잭션을 폐기한다.

2. 장애와 회복

2.1 장애의 유형

트랜잭션 장애

  • 의미
    트랜잭션 수행 중 오류가 발생하여 정상적으로 수행을 계속할 수 없는 상태

  • 원인
    트랜잭션의 논리적 오류, 데이터 입력 오류, 시스템 자원 과다 사용, 처리 대상 데이터 부재 등

시스템 장애

  • 의미
    하드웨어의 결함으로 정상적으로 수행할 수 없는 상태

  • 원인
    하드웨어 이상으로 메인 메모리 저장 정보 손실 및 교착 상태 발생 등

미디어 장애

  • 의미
    디스크 장치 결함으로 디스크 저장 데이터베이스의 일부 혹은 전체가 손상된 상태

  • 원인
    디스크 헤드의 손상이나 고장 등

2.2 데이터베이스의 저장 연산

저장 장치는 장애 발생 시 대응 방법에 따라 다음과 같이 세 종류로 분류한다.

일반적으로 데이터베이스는 비휘발성 메모리에 상주하지만, 데이터를 처리하기 위해서는 데이터를 메모리로 가져와 이를 처리한 후 그 결과를 다시 디스크로 보내는 작업이 필요하다.

디스크와 메인 메모리 간의 데이터 이동은 블록(block) 단위로 수행된다.
블록을 메인 메모리로 가져오는 작업을 input(X) 연산으로,
메모리에 있는 데이터 X를 디스크 블록으로 이동시키는 것을 output(X) 연산으로 수행한다.

메모리와 응용 프로그램 변수 간의 데이터 이동 작업도 필요하다.
이는 read(X)write(X)연산으로 수행된다.

2.3 회복 기법

DBMS에 있는 회복 관리자(recovery manager)가 회복을 담당한다.
장애 발생을 탐지하고 장애 발생 시 복구 기능을 제공하여 데이터베이스의 일관성을 유지한다.

2.3.1 회복을 위한 연산

데이터베이스 회복의 핵심 원리는 데이터를 별도의 장소에 미리 복사해두고, 문제 발생 시 복사본을 이용해 원래의 상태로 복원하는 것이다.

데이터를 복사해두는 방식은 다음과 같다.

  • 덤프(dump)
    데이터베이스 전체를 다른 저장 장치에 주기적으로 복사한다.

  • 로그(log)
    데이터베이스에서 변경 연산이 실행될 때마다 데이터를 변경하기 이전 값과 변경 이후 값을 별도의 파일에 기록하는 방법

덤프는 미리 정해둔 주기에 따라 수행한다.

장애가 발생하면 덤프와 로그로 저장해둔 정보를 이용해 복구하는 작업을 수행한다.
가장 기본적인 방법은 redoundo연산을 실행하는 것이다.

  • redo(재실행)
    가장 최근에 저장한 데이터베이스 복사본을 가져온 후 로그를 이용해 실행된 모든 변경 연산을 재실행하여 장애가 발생하기 직전 상태로 복구한다.
  • undo(취소)
    로그를 이용해 지금까지 실행된 모든 변경 연산을 취소하여 데이터베이스를 원래 상태로 복구한다.

redo는 전반적으로 문제가 있는 경우 주로 사용하고, undo는 변경 중이었거나 이미 변경된 내용만 신뢰성을 잃은 경우에 주로 사용한다.

2.3.2 로그 회복 기법

로그 회복 기법은 데이터를 변경한 연산 결과를 데이터베이스에 반영하는 시점에 따라 즉시 갱신 회복 기법지연 갱신 회복 기법으로 나뉜다.

즉시 갱식 회복 기법(immediate update)

  • 즉시 갱신 회복 기법은 트랜잭션 수행 과정에서 데이터를 변경한 연산의 결과를 데이터베이스에 즉시 반영한다. 그리고 장애 발생에 대비하여 이에 대한 내용을 로그 파일에 기록한다.

  • 장애가 발생하면 로그 파일에 기록된 내용을 참조하여, 발생 시점에 따라 redoundo연산을 실행하여 데이터베이스를 복구한다.

    	* `commit`로그 레코드까지 존재하는 상태 -> `redo`
    • start 로그 레코드만 존재하는 상태 -> undo

지연 갱신 회복 기법(deferred update)

  • 트랜잭션 실행 중에는 데이터베이스에 변경 내용을 반영하지 않고, 로그 파일에만 기록해둔다.

  • 실행 도중 장애가 발생한 경우 로그 파일의 내용을 버리기만 하면 된다.

  • 실행 완료(commit로그 레코드가 존재하는 상태) 후 장애가 발생하면 redo연산을 실행한다.

2.3.3 검사 시점 회복 기법

로그 회복 기법은 로그 전체를 분석하여 회복 연산을 실행해야 한다. 이 방법은 회복에 많은 시간을 소모하고, redo연산이 필요 없는 트랜잭션에도 redo연산을 수행하는 낭비가 발생하기도 한다.

이를 해역하기 위해 검사 시점 회복 기법이 제안된다.

작동 원리

  • 일정 시간 간격의로 검사시점을 기록한다.
  • 장애 발생 시 최근 검사 시점 이전 트랜잭션은 회복 작업을 하지 않고, 이후의 트랜잭션에만 회복 작업을 수행한다.

2.3.4 미디어 회복 기법

  • 디스크 장애 발생에 대비한 회복 기법이다.

  • 전체 데이터베이스를 일정 주기로 다른 안전한 장치에 복사해두는 덤프(dump)를 이용한다.

  • 전체 데이터베이스를 복사하는 작업은 비용이 많이 들기 때문에 CPU가 낭비된다는 단점이 있다.

3. 병행 제어(concurrency control)

3.1 병행 수행과 병행 제어

병행제어란 데이터베이스를 여러사용자가 동시에 공유하고 접근할 수 있도록 제어하는 것이다.

동시성 제어라고도 한다.

3.2 병행 수행의 문제

병행 수행 시 발생할 수 있는 대표적인 문제로 갱신 분실, 모순성, 연쇄복귀가 있다.

2.1 갱신 분실(lost update)

하나의 트랜잭션이 수행한 데이터 변경 연산의 결과를 다른 트랜잭션이 덮어써 변경 연산이 무효화 되는 것.

운영체제 race condition 발생과 동일한 원리이다.

만약 두개의 트랜잭션이 병행수행 될 때, 1번 트랜잭션이 변수 X에 대한 연산을 저장하기 전에 2번 트랜잭션이 변수 X값을 읽어간다면, 1번 트랜잭션의 연산은 무시된다.

2.2 모순성(inconsistency)

한 트랜잭션이 여러개의 변수에 대한 연산을 진행할 때, 각 변수가 같은 시점에 있는 것이 보장되지 않는다(일관성이 없다)

트랜잭션 T1과 T2가 XY값에 대해 연산할 때,
T1-> X변경
T2-> X,Y변경
T1-> Y변경
과 같은 순서로 트랜잭션이 수행된다면, T1에서 X,Y는 각각 읽어들인 시점(T2의 연산 전,후)이 달라지게 된다.

즉 일관성 없는 데이터베이스 상태로 인해 모순이 발생한다.

2.3 연쇄 복귀(cascading rollback)

트랜잭션 완료 전 장애 발생시 rollback연산을 수행하는데, 이 트랜잭션이 변경한 데이터를 가져가 변경 연산을 실행한 또 다른 트랜잭션에도 rollback연산을 수행해야한다.

만약 또 다른 트랜잭션이 이미 완료된 상태라면 rollback연산을 실행할 수 없는 문제가 발생한다.

3.3 트랜잭션 스케줄

인터리빙(interliving)

트랜잭션들이 차례로 번갈아가며 수행되는 방식

3.3.1 직렬 스케줄(serial schedule)

인터리빙 방식을 이용하지 않고 각 트랜잭션별로 연산들을 순차적으로 실행시킨다.

  • 모든 트랜잭션이 완료될 때 까지 다른 트랜잭션의 방해를 받지 않는다.
  • 항상 모순이 없는 정확한 결과를 얻는다.

하지만 트랜잭션이 동시에 수행되는 것이 아니기 때문에 일반적으로 잘 사용하지 않는다.

3.3.2 비직렬 스케줄(nonserial schedule)

인터리빙 방식을 이용하여 트랜잭션을 병행해서 수행시킨다.

  • 하나의 트랜잭션이 완료되기 전에 다른 트랜잭션의 연산이 수행될 수 있다.
  • 정확한 결과를 보장하지 않는다.

3.3.3 직렬 가능 스케줄(serializable schedule)

정확한 결과를 보장하는 비직렬 스케줄이다.

비직렬 스케줄에서 직렬 가능 스케줄을 판별해내는 것은 간단한 작업이 아니다.

따라서 직렬 가능 스케줄인지 검사하기보다는 직렬 가능성을 보장하는 병행 제어 기법을 사용한다.

3.4 병행 제어 기법

병행 제어의 기본 원리는 모든 트랜잭션이 따르면 직렬 가능성이 보장되는 규약을 정의하고 이를 따르도록 하는 것이다.

3.4.1 로킹 기법의 개념

동시에 같은 데이터에 접근하지 못하도록 lockunlock이라는 2개의 연산을 이용해 제어한다.
즉 상호 배제(mutual exclusion)을 보장함으로써 직렬 가능성을 보장한다.

로킹 단위

로킹을 실행하는 대상 데이터의 크기는 데이터베이스 전체부터 데이터베이스를 구성하는 속성까지 다양하다.

  • 범위를 크게 하면 제어는 쉽지만 병행성은 떨어진다.
  • 반대로 범위가 작으면 병행성은 커지지만 제어가 어렵다.

적절한 로킹 단위설정도 중요하다.

처리 효율성을 높이기 위한 로킹의 구분

read연산에 대해서는 다른 트랜잭션과 동시에 실행할 수 있도록 하여 처리 효율성을 높인다.
이를 공용lock과 전용lock으로 구분한다.

기본 로킹 기법만으로는 직렬 가능성을 완벽히 보장하지 않는다.
모순성에 대한 완벽한 해결책이 아니기 때문이다.
이를 위해 2단계 로킹 규약이 제안된다.

3.4.2 2단계 로킹 규약

lockunlock연산을 2단계로 나누어 실행한다.

트랜잭션 자체를 확장->축소 구조로 구성한다.
즉 트랜잭션에서 사용하는 공통 변수에 대해서 lock을 모두 실행한 후에 unlock을 차례로 수행하는 방식이다.

이렇게 하면 직렬가능성도 보장하지만 교착상태(deadlock)이 발생한 수 있다.

교착상태는 처음부터 발생하지 않도록 예방하거나, 발생했을 때 빨리 탐지하여 필요한 조치를 취하는 방법으로 해결한다.

Reference

IT CookBook, 데이터베이스 개론(2판): 기초 개념부터 빅데이터까지_김연희

0개의 댓글