데이터베이스 정리

초코칩·2024년 1월 23일

Computer Science

목록 보기
3/4

관계 데이터 모델의 개념

릴레이션

릴레이션은 행과 열로 구성된 테이블을 말한다.

릴레이션 스키마와 인스턴스

릴레이션은 스키마와 인스턴스로 이루어진다. 스키마는 관계형 데이터베이스의 릴레이션이 어떻게 구성되는지 어떤 정보를 담고 있는지에 대한 기본적인 구조를 정의한다. 테이블에서 스키마는 테이블의 첫 행인 헤더에 나타나며 각 데이터의 특징을 나타내는 속성, 자료 타입 등의 정보를 담고 있다. 인스턴스는 정의된 스키마에 따라 테이블에 실제로 저장되는 데이터의 집합을 의미한다.

릴레이션 스키마

릴레이션 스키마는 릴레이션에 어떤 정보가 담길지를 정의한다.

  • 속성: 릴레이션 스키마의 열
  • 도메인: 속성이 가질 수 있는 값의 집합
  • 차수: 속성의 개수

릴레이션 인스턴스

릴레이션 인스턴스는 릴레이션 스키마에 실제로 저장된 데이터의 집합이다. 릴레이션에서 한 행을 튜플이라고 부르며, 각 튜플의 속성 값은 릴레이션 스키마에서 정의한 도메인 값으로 구성되며 튜플이 가지는 속성의 개수는 릴레이션 차수와 동일하다. 또한 릴레이션 내의 모든 튜플들은 서로 중복되지 않아야 한다.

데이터베이스에서 뷰(View)는 하나 이상의 테이블에서 선택적으로 특정 열이나 행을 가진 가상의 테이블이나 쿼리 결과를 나타냅니다. 뷰는 실제 데이터를 저장하지 않고, 데이터베이스에 저장된 테이블의 구조와 데이터에 대한 쿼리를 단순화하고 추상화하는 데 사용됩니다.

장점

  • 쿼리 간소화: 뷰는 복잡한 쿼리나 조인을 간소화하고, 필요한 열이나 행에 대한 데이터에 쉽게 접근할 수 있도록 도와준다.
  • 보안 및 권한 관리: 특정 사용자에게 필요한 데이터만 노출할 수 있으며, 뷰를 통해 열을 가려서 민감한 정보를 보호할 수 있다.
  • 물리적인 공간이 필요하지 않다

단점

  • 뷰에 인덱스를 구성할 수 없다.
  • 뷰를 포함하여 뷰를 만든 경우 연관 뷰를 삭제하면 생성된 뷰도 삭제된다.
  • 한 번 정의된 뷰는 수정이 불가하다.

조인

무결성 제약조건

데이터베이스에 저장된 데이터는 결함이 없어야 하며 질의에 대해 신뢰성 있는 답을 제공해야 한다.

RDBMS에서 키는 릴레이션에서 특정 튜플을 식별할 때 사용하는 속성 혹은 속성의 집합이다. 릴레이션은 중복된 튜플을 허용하지 않기 때문에 각각의 튜플에 포함된 속성들 중 하나는 값이 달라야한다. 즉 키가 되는 속성(혹은 속성의 집합)은 반드시 값이 달라서 튜플들을 서로 구별할 수 있어야 한다.

키는 각 릴레이션의 튜플을 유일하게 식별하는 장치이며 동시에 각 릴레이션 간의 관계를 말해주는 연결고리다.

슈퍼키

슈퍼키는 튜플을 유일하게 식별할 수 있는 하나의 속성 혹은 속성의 집합을 말한다.

튜플을 유일하게 식별할 수 있는 값이면 모두 슈퍼키가 될 수 있다. 슈퍼키는 포함하지 않아도 되는 속성을 포함할 수 있다.

  • (주민번호), (주민번호, 이름), (주민번호, 이름, 주소), ...

우리가 관심을 두어야할 것은 튜플을 식별할 수 있는 최소한의 속성 집합이다. 키를 구성하는 속성이 많으면 그만큼 관계 표현이 복잡해지고 사용에도 불편이 따른다.

후보키

후보키는 튜플을 유일하게 식별할 수 있는 속성의 최소 집합이다. 예를 들어 (주민번호, 이름)은 슈퍼키이지만 후보키는 아니다.

기본키

기본키는 여러 후보키 중 하나를 선정하여 대표로 삼는 키를 말한다. 후보키가 하나뿐이라면 그 후보키는 사용하면 되고 여러 개라면 릴레이션의 특정을 반영하여 하나를 선택하면 된다.

기본키 선정 고려사항

  • 릴레이션 내 튜플을 식별할 수 있는 고유한 값을 가져야한다.
  • NULL 값은 허용하지 않는다.
  • 키 값의 변동이 일어나지 않아야 한다.
  • 최대한 적은 수의 속성을 가져야 한다.
  • 키를 사용하는데 있어 문제 발생 소지가 적어야 한다.

대리키

기본키가 보안을 요하거나, 마땅한 기본키가 없을 경우 가상의 속성을 만들어 기본키로 삼는 경우가 있다. 이러한 키를 대리키 또는 인조키라고 한다. 대리키는 DBMS나 관련 SW에서 임의로 생성하는 값으로 사용자가 직접 그 값의 의미를 알 수 없다.

대체키

대체키는 기본키로 선정되지 않은 후보키를 말한다.

외래키

외래키는 다른 릴레이션의 기본키를 참조하는 속성을 말한다. 외래키는 다른 릴레이션의 기본키를 참조하여 데이터 모델의 특징인 릴레이션 간의 관계를 표현한다.

외래키가 성립하기 위해서는 참조하고 참조되는 양쪽 릴레이션의 도메인이 서로 같아야 한다. 또한 참조되는 릴레이션의 기본키 값이 변경되면 이 기본키를 참조하는 외래키 값 역시 변경되어야 한다. 참조하는 외래키 값이 참조되는 기본키 값에 연동된다는 의미로, 외래키는 항상 데이터의 일관성을 유지해야 한다. 이러한 특징을 외래키 제약조건이라고 한다. 외래키(참조하는 키)는 참조되는 릴레이션의 기본키와 달리 NULL 값을 포함할 수 있고 중복 값도 허용한다.

외래키 사용 시 참조하는 릴레이션과 참조되는 릴레이션이 꼭 다른 릴레이션일 필요는 없다. 즉 자기 자신의 기본키를 참조할 수도 있다.

정리

무결성 제약조건

데이터 무결성은 데이터베이스에 저장된 데이터의 일관성과 정확성을 지키는 것을 말한다. 일관성과 정확성을 잃어버린 데이터베이스는 정보로서의 가치에 심각한 문제가 있는 것이다. 일관성과 정확성을 가지고 구축된 데이터베이스가 계속해서 무결성을 유지하려면 튜플의 삽입, 삭제, 수정 시 데이터의 제약조건 준수 여부를 확인하여야 한다.

실제 데이터의 삽입, 삭제, 수정에 관련된 문제는 응용 프로그램 개발 단계에서 프로그래머가 일일이 처리할 수 있다. 그러나 모든 경우를 감안하여 프로그램을 작성하기도 어렵고 향후 유지하기도 어렵다. 이 경우 데이터의 삽입, 삭제, 수정 시 필요한 기본적인 제약조건을 DBMS가 알아서 지켜준다면 프로그래머의 부담을 줄일 수 있다. 프로그래머는 데이터 변동에 따른 대응에 필요 이상의 시간을 투자하지 않고 프로그래밍에 집중할 수 있고, 소프트웨어의 성능 및 데이터의 신뢰성 향상에도 큰 도움을 줄 수 있다.

무결성 제약조건에는 튜플에 삽입 가능한 데이터의 값을 제한하는 도메인 무결성 제약조건과 관계 데이터 모델의 핵심적인 관계 표현을 위한 개체 무결성 제약 조건, 참조 무결성 제약 조건이 있다.

도메인 무결성 제약조건

도메인 무결성 제약조건은 도메인 제약이라고도 하며, 릴레이션 내의 투플들이 각 속성의 도메인에 지정된 값만을 가져야 한다는 조건이다. 예를 들어 주문 릴레이션에서 주문일자는 날짜 데이터만 사용해야 한다. 만약 영문자 등의 다른 자료 형을 사용한다면 자료의 저장 및 검색에 큰 어려움이 따를 것이다. 도메인 무결성 제약조건은 속성 값과 관련된 무결성으로, SQL 문에서 데이터 형식, null/not null, 기본 값, 체크 등을 사용하여 지정할 수 있다.

개체 무결성 제약조건

개체 무결성 제약조건은 기본키 제약이라고도 한다. 릴레이션은 기본키를 지정하고 그에 따른 무결성 원칙 즉, 기본키는 NULL 값을 가져서는 안되며 릴레이션 내에 오직 하나의 값만 존재해야 한다는 조건이다. 개체 무결성 제약조건은 참조 무결성 제약조건과 함께 관계 데이터 모델의 핵심 개념이다.

참조 무결성 제약조건

참조 무결성 제약조건은 외래키 제약이라고도 한다. 릴레이션 간의 참조 관계를 선언하는 제약조건이다. 일반적으로 참조되는(제공하는) 릴레이션을 부모 릴레이션, 참조하는(제공받는) 릴레이션을 자식 릴레이션이라고 한다. 참조 무결성 제약조건은 자식 릴레이션의 외래키는 부모 릴레이션의 기본키와 도메인이 동일해야 하며, 자식 릴레이션의 값이 변경될 때 부모 릴레이션의 제약을 받는다는 것이다. 즉 부모 릴레이션의 도메인과 다른 값으로 삽입, 수정될 경우 거부되고, 반대로 자식 릴레이션에서 참조하고 있는 값을 부모 릴레이션에서 삭제하거나 다른 값으로 변경하려고 하면 거부된다.

무결성 제약조건 수행

릴레이션은 데이터의 변경이 일어날 때 제약조건에 위배될 수 있다. 따라서 제약조건의 준수 여부는 데이터의 변경(삽입, 수정, 삭제)이 있을 때마다 확인해야 한다. 예를 들어 기존의 기본키와 같은 값을 가진 튜플을 삽입하거나, 기존의 기본키 값을 다른 투플의 기본키와 같은 값으로 변경한다면 그 연산은 거부된다. 또 부모 릴레이션에서 투플을 삭제할 경우 자식 릴레 이션도 같이 처리를 해야 한다.

각각의 제약조건에 대해 데이터의 변경이 일어나면 어떻게 수행되는지 살펴보자.

개체 무결성 제약조건

관계 데이터베이스 시스템에서 DBMS는 투플을 삽입하거나 수정할 때마다 개체 무결성 제약 조건을 지키는지 확인한다. 즉 기본키 값이 유일한지, NULL 값이 아닌지를 검사한다. 만약 조건에 맞지 않으면 삽입 연산을 거부하고 오류 메시지를 보낸다.

삽입

새로운 튜플이 삽입되는 과정을 살펴보자. DBMS는 도메인 무결성 제약조건을 확인한 후 개체 무결성 제약조건을 수행하기 위해 학생 릴레이션을 살펴본다. 그런데 기본키인 학번에 이미 존재하면 삽입을 거부한다. 또 다른 PK가 NULL인 투플의 삽입 역시 기본키가 NULL이기 때문에 기존 투플을 검색할 필요도 없이 거부한다.

수정

수정 연산 역시 삽입 연산과 동일한 제약에 따라 처리된다. 수정하려고 한다면 DBMS는 동일한 값이 존재하는지 검색한 후 수정을 거부한다.

삭제

특별한 확인이 필요하지 않으며 즉시 수행한다. 단, 참조 무결성 제약조건에 의하여 학생 릴 레이션의 기본키를 다른 릴레이션에서 외래키로 참조하고 있으면 바로 삭제하지 않는다. 자 세한 내용은 이어서 설명하는 참조 무결성 제약조건에서 다룬다.

참조 무결성 제약조건

참조 무결성 제약조건은 개체 무결성 제약조건과 달리 단일 릴레이션에 대한 내용이 아니다. 따라서 참조 무결성 제약조건을 준수하기 위해서는 두 릴레이션 간의 참조 관계에 따라 좀 더 복잡한 처리를 수행해야 한다. 부모 릴레이션(기본키가 참조되는 릴레이션)과 자식 릴레이션 (기본키를 참조하는 릴레이션)의 관계를 [그림 2-14]의 학생관리 데이터베이스를 통해 살펴 보자. 학과 릴레이션이 부모 릴레이션이고, 학생 릴레이션이 자식 릴레이션이다.

삽입

학생 릴레이션에 새로운 튜플이 삽입되는 과정을 살펴보자. DBMS는 먼저 도메인 무결성 제약조건을 확인한 후 개체 무결성 제약조건에 위배되는 값이 없는지 확인한다. 이후 PK가 부모 릴레이션의 기본키에 존재하는지 확인한다. 그런데 부모 릴레이션에 없으면 삽입은 거부된다. 이 경우 부모 릴레이션에 해당 PK를 삽입한 후 수행하면 정상적으로 진행된다. 참고로 릴레이션 생성 시 외래키인 PK 속성에 NULL 값을 허용하였다면 PK 값이 없어도 삽입이 가능하다.

삭제

삽입과는 반대로 자식 릴레이션에서 투플이 삭제되는 경우 부모 릴레이션에는 아무런 영향을 주지 않으므로 바로 삭제가 가능하다. 그러나 부모 릴레이션에서 튜플이 삭제되는 경우에는 문제가 발생할 수 있다. 이 문제에 대한 조치 방법으로 다음과 같은 네 가지를 고려할 수 있다.

  • 즉시 작업을 중지
  • 자식 릴레이션의 관련 투플을 삭제
  • 초기에 설정된 다른 어떤 값으로 변경
  • NULL 값으로 설정

이와 같이 DBMS는 부모 릴레이션에서 투플을 삭제할 때 참조 무결성 제약조건을 수행하기 위한 네 가지 옵션이 있다. 이는 제약조건 선언 시 자식 릴레이션에도 지정해주어야 한다.

참조 무결성 제약조건의 옵션(부모 릴레이션에서 투플을 삭제할 경우)
명령어의미
RESTRICTED자식 릴레이션에서 참조하고 있을 경우 부모 릴레이션의 삭제 작업을 거부함학과 릴레이션의 투플 삭제 거부
CASCADE자식 릴레이션의 관련 투플을 같이 삭제함학생 릴레이션의 관련 투플을 삭제
DEFAULT자식 릴레이션의 관련 투플을 미리 설정해둔 값으로 변경함학생 릴레이션의 학과가 다른 학과로 자동 배정
NULL자식 릴레이션의 관련 투플을 NULL 값으로 설정함(NULL 값을 허가한 경우)학생 릴레이션의 학과가 NULL 값으로 변경

수정

수정은 삭제와 삽입 명령이 연속해서 수행된다고 보면 된다. 부모 릴레이션의 수정이 일어날 경우 삭제 옵션에 따라 처리된 후 문제가 없으면 다시 삽입 제약조건에 따라 처리된다.

인덱스

왜 필요한가

RDBMS에서 검색 연산의 속도를 높이기 위한 방법으로 항상 정렬된 상태를 유지하므로 탐색이 빠르다. 하지만 데이터 삽입/삭제/수정 시에는 추가적인 작업이 필요하므로 실행 속도가 느려진다.

저장 성능을 희생하고 데이터 읽기 속도를 높이는 기능

자료구조

  • B-Tree : 일반적으로 사용됨
  • Hash : 해시 값을 계산해 검색하므로 빠르나 부분 검색을 할 수 없다.

인덱스

인덱스란 자료를 쉽고 빠르게 찾기 위한 데이터 구조이다. RDBMS에서 검색 연산의 속도를 높이기 위한 방법으로 항상 정렬된 상태를 유지하므로 탐색이 빠르다. 하지만 데이터 삽입/삭제/수정 시에는 추가적인 작업이 필요하므로 실행 속도가 느려진다.

저장 성능을 희생하고 데이터 읽기 속도를 높이는 기능

자료구조

  • B-Tree : 일반적으로 사용됨
  • Hash : 해시 값을 계산해 검색하므로 빠르나 부분 검색을 할 수 없다.

특징

  • 테이블에서 한 개 이상의 속성을 이용하여 생성한다.
  • 빠른 검색과 함께 효율적인 레코드 접근이 가능하다.
  • 순서대로 정렬된 속성과 데이터의 위치만 보유하므로 테이블보다 작은 공간을 차지한다.
  • 저장된 값들은 테이블의 부분집합이 된다.
  • 일반적으로 B-Tree 형태의 구조를 가진다.
  • 데이터의 수정, 삭제 들의 변경이 발생하면 인덱스의 재구성이 필요하다.

MySQL 인덱스

MySQL의 인덱스는 클러스터드 인덱스와 secondary index로 나누어지며 모두 B-tree 인덱스를 기본으로 한다.
클러스터드 인덱스는 연속된 키 값의 레코드를 묶어서 같은 블록에 저장하는 방법으로 테이블당 하나만 생성할 수 있으며 B-tree 인덱스의 리프 노드에서 페이지의 주소 값 대신 테이블의 열 자체가 저장되는 형태이다.
보조 인덱스의 경우 속성의 값으로 B-tree 인덱스를 구성하며 리프 노드의 각 행은 해당 페이지의 주소 값을 저장한다.

클러스터드 인덱스

클러스터드 인덱스는 인덱스의 리프 노드들이 정렬된 상태로 저장된 테이블 자체가 된다.
이러한 클러스터 인덱스는 테이블당 하나만 생성할 수 있으며, 키 값에 의한 동등 및 범위 (BETWEEN) 검색 모두에 유리하다.
테이블의 데이터가 키 값에 따라 정렬된 형태로 저장 되 어 특정 값을 쉽게 찾을 수 있으며 범위로 검색한다고 해도 이미 정렬되어 있으므로 손쉽게 검색할 수 있다. 또한 인덱스 페이지가 단순해지 인덱스 저장 시 차지하는 공간도 작다. 클러스터드 인덱스는 테이블 생성 시 기본키(PK)를 생성하면 자동으로 생성된다.

  • 기본적인 인덱스로 테이블 생성 시 키본키를 지정하면 기본 키에 대하여 클러스터드 인덱스를 생성한다.
  • 기본키를 지정하지 않으면 먼저 나오는 UNIQUE 속성에 대하여 클러스터드 인덱스를 생성한다.
  • 기본키나 UNIQUE 속성이 없는 테이블은 MySQL이 자체 생성한 행번호(Row ID)를 이용하여 클러스터드 인덱스를 생성한다.

Secondary 인덱스

Secondary 인덱스는 테이블당 여러 개를 만들 수 있다. 테이블의 컬럼(속성) 하나만을 대상으로 단일 컬럼 인덱스뿐만 아니라 여러 개의 컬럼을 복합적으로 결합하여 사용하는 인덱스도 만들 수 있다.
한 가진 더 알아둘 내용은 인덱스를 사용하여 검색할 경우 인덱스와 데이터 파일의 구조적인 특징으로 인해 특정 키 값을 찾는 검색의 경우는 성능을 보장할 수 있으나. 범위 검색은 데이터가 저장된 Block 값들의 저장 순서가 일정치 않을 수 있어서 원하는 만큼의 빠른 검색 효과 를 보장할 수 없다는 점이다. 그러므로 인데스 구성 시 자료의 저장 및 질의 형태에 따라 신중 하게 생성해야 한다.

  • 클러스터 인덱스가 아닌 모든 인덱스는 보조 인덱스이며 보조 인덱스의 각 레코드는 보조 인덱스 속성 과 기본키 속성 값을 갖고 있다.
  • 보조 인덱스를 검색하여 기본키 속성 값을 찾은 다음 클러스터 인덱스로 가서 해당 레코드를 찾는다.

이상현상

잘못 설계된 테이블로 삽입, 삭제, 수정 같은 데이터 조작을 하면 이상현상이 일어난다. 이상 현상이란 테이블에 투플을 삽입할 때 부득이하게 NULL 값이 입력되거나, 삭제 시 연쇄삭제 현상이 발생하거나, 수정 시 데이터의 일관성이 훼손되는 현상을 말한다.

삭제 이상

튜플 삭제 시 같이 저장된 다른 정보까지 연쇄적으로 삭제되는 현상이다. 위 그림에서 장미란 선수가 스포츠 경영학을 수강 취소해서 삭제하면, 학생의 학과와 주소가 연쇄적으로 삭제되게 된다.

삽입 이상

튜플 삽입 시 특정 속성에 해당하는 값이 없어 NULL 값을 입력해야 하는 현상이다. 위 그림에서 박세리 학생이 아직 수강 신청을 안했기 때문에 NULL 값이 입력되게 된다.

수정 이상

튜플 수정 시 중복된 데이터의 일부만 수정되어 데이터의 불일치 문제가 발생하는 현상이다. 위 그림에서 박지성 선수의 주소가 일부 레코드만 변경되게 된다.

함수 종속성

어떤 속성 A의 값을 알면 다른 속성 B의 값이 유일하게 정해지는 의존 관계를 속성 B는 속성 A에 종속한다. 혹은 속성 A는 속성 B를 결정한다.라고 한다. 이 관계를 A ⟶ B로 표기하며, A는 B의 결정자라고 하고, B는 종속 속성이라고 한다.

정규화

이상현상의 원인은 여러 가지가 있는데, 대부분 두 가지 이상의 정보가 한 릴레이션에 저장되어 있기 때문에 발생한다. 따라서 이상현상은 릴레이션을 분해하여 제거한다. 분해된 릴레이 션에 이상현상이 남아 있다면 이상현상이 없어질 때까지 분해한다. 이상현상이 발생하는 릴레이션을 분해하여 이상현상을 없애는 과정을 정규화라고 한다.

이상현상이 있는 릴레이션은 이상현상을 일으키는 함수 종속성의 유형에 따라 등급을 구분할 수 있다. 정규형이 높을수록 이상현상은 줄어든다.

제 1정규형

제 1정규형은 릴레이션의 속성 값이 원자값이어야 한다는 조건이다.

제 2정규형

제 2정규형은 모든 비주요 속성이 기본 키에 완전 함수 종속되어야 한다. 즉 릴레이션이 부분 함수 종속성을 갖지 않는 것을 의미한다.

함수 종속성

함수 종속성이란 어떤 릴레이션 R에 대하여, 제목의 부분집합 두 개를 A, B라고 하자. 릴레이션 R의 모든 튜플이 A의 값이 같다면 B의 값도 같은 경우가 있을 수도 있다. 이 경우에 한해서 B는 A에 함수 종속한다고 하고, 이러한 과정을 A -> B라고 기술한다.

A의 값을 알면 B의 값을 알 수 있다는 의미다. A값이 다르고 B의 값이 같아도 문 없다.

제 3정규형

테이블 내의 속성 간에 이행적 종속이 없어야 한다.

BCNF

릴레이션에 존재하는 함수 종속성에서 모든 결정자가 후보키이면 BCNF 정규형이다.

무손실 분해

트랜잭션

트랜잭션은 DBMS에서 데이터를 다루는 논리적인 작업의 단위이다. 보통 단일 SQL 문을 사용하여 다루기도 하지만 여러 개의 SQL 문을 순차적으로 수행하여 다루기도 한다. 데이터베이스에서 트랜잭션을 정의하는 이유는 다음과 같다.

  • 데이터베이스에서 데이터를 다룰 때 장애가 일어나는 경우가 있다. 트랜잭션은 장애 발생 시 데이터를 복구하는 작업의 단위가 된다.
  • 데이터베이스에서 여러 작업이 동시에 같은 데이터를 다룰 때가 있다. 트랜잭션은 이 작업을 서로 분리하는 단위가 된다.

트랜잭션 수행 과정을 정리하면 아래와 같다. 트랜잭션은 시작 - 수행 - 부분완료 - 완료의 과정을 거치게 된다. 부분완료는 트랜잭션의 종료를 사용자나 다른 트랜잭션에게 알리는 단계이다. 부분완료된 트랜잭션은 DBMS가 다른 트랜잭션의 작업 처리 상황을 고려하여 변경 내용을 하드디스크에 기록한다. 기록이 끝나면 완료를 하고, 그 후에는 다른 트랜잭션이 데이터를 자유롭게 사용할 수 있다.

트랜잭션 성질

  • 원자성: 트랜잭션에 포함된 작업은 전부 수행되거나 아니면 수행되지 않아야 한다.
  • 일관성: 트랜잭션을 수행하기 전이나 후나 데이터베이스는 항상 일관된 상태를 유지해야 한다.
  • 고립성: 수행 중인 트랜잭션에 다른 트랜잭션이 끼어들어 변경 중인 데이터 값을 훼손하는 일이 없어야 한다.
  • 지속성: 수행을 성공적으로 완료한 트랜잭션은 변경한 데이터를 영구히 저장해야 한다.

원자성

원자성이란 일부만 수행되는 일이 없도록 전부 수행하거나 아예 수행하지 않아야 한다. SQL에서는 트랜잭션의 시작과 끝을 표시하기 위해 START TRANSACTION ... COMMIT 문을 사용한다. 트랜잭션 중간에 작업이 잘못되면 회복 알고리즘을 이용하여 변경한 내용을 취소한다(자의적으로 트랜잭션을 취소하는 명령어 ROLLBACK을 사용하기도 한다). COMMIT과 ROLLBACK 명령어는 트랜잭션 제어 명령어라고 한다.

표준 명령어문법설명
START TRANSACTIONSET TRANSACTION트랜잭션 시작
COMMITCOMMIT트랜잭션 종료
ROLLBACKROLLBACK {TO <savepoint>}트랜잭션을 전체 혹은 <savepoint>까지 무효화시킨다
SAVESAVEPOINT <indentifier><savepoint>를 만든다

트랜잭션의 길이가 길면 트랜잭션의 중간 지점에 수정 내용을 반영하는 포인트를 만드는데, 이를 SAVEPOINT라고 한다. 트랜잭션이 잘못되어 처음부터 다시 실행해야 하는 경우 트랜잭션의 처음이 아니라 SAVEPOINT까지 되돌아가면 트랜잭션 전체가 ROLLBACK되는 것을 막을 수 있다. SAVEPOINT는 트랜잭션 내에서 여러 개를 만들 수 있다.

일관성

트랜잭션은 데이터베이스의 일관성을 유지해야 한다. 여기서 일관성이란 테이블이 생성될 때 CREATE 문과 ALTER 문의 무결성 제약조건을 통해 명시된다. 다만 수행 중 일시적으로 일관성을 유지하지 못하는 상태가 있을 수도 있다.

고립성

데이터베이스는 공유가 목적이기 때문에 여러 트랜잭션이 동시에 수행된다. 이때 각 트랜잭션은 다른 트랜잭션의 방해를 받지 않고 독립적으로 작업을 수행한다. 이렇게 여러 트랜잭션이 동시에 수행될 때 상호 간섭이나 데이터 충돌이 일어나지 않는 형상을 고립성이라고 한다.

같은 시간대에 여러 트랜잭션이 같은 데이터를 읽고 쓸 경우, 변경 중인 데이터를 다은 트랜잭션이 사용하면 데이터의 일관성이 훼손될 수 있다. 따라서 동시에 수행되는 트랜잭션이 같은 데이터를 가지고 충돌하지 않도록 제어하는 작업이 필요하다. 이 작업을 동시성 제어라고 한다.

지속성

트랜잭션이 정상적으로 완료 혹은 부분완료한 데이터는 반드시 데이터베이스에 기록되어야 한다. 이러한 성질을 트랜잭션의 지속성이라고 한다. DBMS 복구 시스템은 트랜잭션이 작업한 내용을 수시로 로그 데이터베이스에 기록했다가 문제가 발생하면 로그 파일을 이용하여 복구 작업을 수행한다. 즉 시스템이 멈추어도 트랜잭션 수행으로 변경된 내용은 디스크에 기록된다.

트랜잭션 상태도는 아래와 같다. 트랜잭션은 수행을 완료하면 부분완료 혹은 실패 상태 중 하나가 된다. DBMS는 부분완료 상태에서는 작업한 내용을 데이터베이스에 반영하고, 실패 상태에서는 작업한 내용을 취소한다.

  • 부분완료: 트랜잭션 수행을 완료되었지만 변경 내용이 데이터베이스에 기록되었는지 확실하지 않은 상태이다. 이 상태에서는 DBMS가 최종적으로 변경 내용을 데이터베이스에 기록해야 완료 상태가 된다. 만약 시스템 내부의 문제 혹은 시스템 다운 등으로 DBMS가 변경 내용을 데이터베이스에 기록하지 못하면 실패 상태가 된다.
  • 실패: 트랜잭션 중간에 중단했거나 부분완료 상태에서 변경 내용을 DB에 저장하지 못한 상태를 말한다. 실패 상태에서 DBMS는 트랜잭션이 수행한 작업을 모두 원상복구 시킨다.

트랜잭션과 DBMS

DBMS는 트랜잭션이 ACID를 유지할 수 있도록 지원한다. 먼저 원자성을 유지하기 위해 회복(복구) 관리자 프로그램을 작동시킨다. 회복 관리자 프로그램은 데이터베이스가 변경한 내용을 로그로 기록하고 있다가 트랜잭션에 문제가 생겼을 때 원래 상태로 되돌린다.

DBMS는 일관성을 유지하기 위해 무결성 제약조건을 활용한다. 트랜잭션 수행 시 데이터에 변경이 가해지면 미리 정의해 둔 무결성 제약조건을 검사하여 일관성이 깨지는 것을 막는다. 그런데 두 개의 트랜잭션이 동시에 수행될 때 트랜잭션 간에 간섭으로 일관성이 깨지는 현상은 무결성 제약조건을 검사하는 것으로 해결할 수 없다. 동시에 같은 데이터를 접근하는 트랜잭션들이 질서 있게 접근하여 데이터베이스의 일관성을 유지하도록 하기 위해서는 동시성 제어 알고리즘을 작동시켜야 한다.

DBMS는 고립성을 유지하기 위해 일관성을 유지하는 것과 마찬가지로 동시성 제어 알고리즘을 작동시킨다. 두 개의 트랜잭션이 동시에 수행될 때 간섭에 의하여 데이터 값이 손상되면 고립성이 깨진다. 이 경우 동시성 제어 알고리즘을 작동시켜 여러 트랜잭션이 동시에 같은 데이터를 접근할 때 마치 한 트랜잭션씩 순서대로 접근하는 것처럼 제어한다. DBMS는 지속성을 유지하기 위해 회복 관리자 프로그램을 이용한다. 회복 관리자 프로그램은 데이터베이스가 변경한 내용을 로그로 기록하고 있다가 트랜잭션에 문제가 있을 때 원래 상태로 되돌린다.

트랜잭션의 4가지 성질과 각 성질을 유지시키는 위한 DBMS의 기능을 그림으로 나타내면 다음과 같다.

동시성 제어

한 개의 트랜잭션이 끝나고 다음 트랜잭션을 수행시키면 데이터베이스의 일관성에 문제가 없다. 그러나 데이터베이스는 공유를 목적으로 하기 때문에 가능한 많은 트랜잭션을 동시에 수행시켜야 한다. 동시에 수행되는 트랜잭션은 다른 트랜잭션이 같은 데이터를 공유하고 있다는 사실을 모를 수 있기 때문에 일관성이 훼손될 수 있다. 트랜잭션이 동시에 수행될 때, 일관성을 해치지 않고 트랜잭션의 데이터 접근을 제어하는 DBMS의 기능을 동시성 제어라고 한다.

두 개의 트랜잭션이 한 개의 데이터에 동시 접근할 때 발생할 수 있는 상황이다.

상황트랜잭션 1트랜잭션 2발생 문제동시 접근
상황 1readread없음허용
상황 2readwriteDirty read, Unrepeatable read, Phantom read허용 또는 불가 선택
상황 3writewriteLost Update허용 불가(Lock 이용)

상황 1은 두 트랜잭션이 각각 읽기만하기에 동시 진행에 아무 문제가 없다. 상황 2는 두 트랜잭션 중 하나가 쓰기 작업을 하는 경우로 트랜잭션 격리 수준으로 동시 접근을 허용 또는 불가하게 할 수 있다. 상황 3은 모두 쓰기 작업으로 Lost Update 문제가 발생할 수 있다.

Lost Update

Lost Update 문제는 두 개의 트랜잭션이 한 개의 데이터를 동시에 갱신할 때 발생한다. Lost Update 문제는 데이터베이스에서 절대 발생하면 안되는 현상이다.

락(Lock)

락은 트랜잭션이 데이터를 읽거나 수정할 때 데이터에 표시하는 잠금 장치이다. 락을 이용하여 자신이 사용할 데이터를 잠그면 다른 트랜잭션은 잠금이 풀릴 때까지 기다려야 한다. 락을 사용하면 데이터에 대한 갱신을 순차적으로 진행할 수 있기 때문에 갱신손실 문제를 해결할 수 있다.

락의 유형

락은 트랜잭션이 다루는 데이터를 다른 트랜잭션이 접근하리 못하도록 막아 대기 상태로 만든다. 다른 트랜잭션을 대기 상태로 만드는 일은 사용자의 응답 시간에 영향을 주기 때문에 가능한 최소화해야 한다.

트랜잭션이 다루는 데이터는 읽기만 하는 데이터, 읽고 쓰는 데이터, 쓰기만 하는 데이터가 있다. 이 중에서 읽기만 하는 데이터가 있다. 이 중에서 읽기만하는 데이터를 다루는 트랜잭션은 어느 정도 허용해도 문제가 없다. 이 점을 고려하여 락의 유형을 두 가지로 분류한다.

고유락 (Shared Lock 또는 Read Lock)

고유락은 여러 트랜잭션이 동일한 자원을 동시에 읽을 수 있도록 허용하는 락이다. 한 트랜잭션이 데이터를 읽고 있을 때, 다른 트랜잭션이 동일한 데이터를 읽을 수 있지만, 이때는 해당 데이터를 수정할 수 없다. 다수의 트랜잭션이 데이터를 읽는 경우에 사용되며, 서로 간섭 없이 읽을 수 있다.

배타락 (Exclusive Lock 또는 Write Lock)

배타락은 특정 자원에 대한 읽기 및 쓰기 권한을 가진 트랜잭션이 독점적으로 해당 자원을 사용할 수 있도록 하는 락이다. 한 트랜잭션이 데이터를 쓰고 있을 때, 다른 트랜잭션이 동일한 데이터를 읽거나 쓸 수 없다. 데이터를 수정하는 경우나 쓰기 작업을 수행할 때 사용된다.

2단계 락킹

락을 사용하면 갱신 손실 문제를 해결할 수 있다. 하지만 락을 걸고 해제하는 시점에 제한을 두지 않으면 두 개의 트랜잭션이 동시에 실행될 때 데이터의 일관성이 깨질 수 있다.

즉, 데이터에 락을 걸었다 풀고 다시 거는 중간 과정에 락의 해지 상태가 생기면서 다른 트랜잭션에게 중간 결과를 보일 수 있다는 것이다. 이것을 방지하기 위해 2단계 락킹 기법을 사용한다. 이 기법은 트랜잭션이 락을 걸고 해제하는 시점을 다음과 같이 2단계로 나누어 진행한다.

  • 확장 단계: 트랜잭션이 필요한 락을 획득하는 단계로, 이 단계에서는 이미 획득한 락을 해체하지 않는다.
  • 수축 단계: 트랜잭션이 락을 해제하는 단계로, 이 단계에서는 새로운 락을 획득하지 않는다.

데드락

2단계 락킹 방법을 사용하면 데이터의 일관성을 유지할 수 있다. 그렇지만 두 개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠질 수 있다. 이러한 현상을 데드락(Deadlock)이라 한다.

데드락은 대기 그래프를 그려 발생 여부를 판단할 수 있다. 대기 그래프는 트랜잭션을 노드로, 락 요청을 화살표로 표현한다. 대기 그래프에서 사이클이 존재하면 데드락이 발생한 것이다.

복원, 백업

profile
초코칩처럼 달콤한 코드를 짜자

0개의 댓글