본문 바로가기

이글루스

수까락의 프로그래밍 이야기

검색페이지 이동

사이드 메뉴

이글루스 블로그 정보

데이터베이스의 기본 구조

앱으로 보기

본문 폰트 사이즈 조절

이글루스 블로그 컨텐츠


1. 데이터베이스의 기본 구조

우선 데이터베이스란? SQLServer의 개체(테이블, 뷰, 인덱스 등)를 저장하기 위한 공간이다.

데이터베이스를 생성하는 가장 간단한 구문은 아래와 같다.

CREATE DATABASE testDB

위 구문에서 데이터베이스 생성시의 'testDB'는 논리적인 이름이다.
즉, 'testDB'는 SQLServer 내에서만 불려지는 이름이며, 이것의 실체는 파일로 존재하게 된다.

파일의 위치는 데이터베이스 속성 중 [파일] 탭에서 아래 그림과 같이 확인할 수 있다.


즉, MSSQLServer 2008을 기본 디렉토리에 설치했다면 경로는 아래와 같다.
C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA

위 그림에서 보듯이 하나의 데이터베이스는 기본적으로 두 개의 파일을 가진다.
  • mdf, ndf : 데이터 파일. 실제 데이터(테이블, 인덱스 등)와 그 행 데이터들이 저장된다
  • ldf : 로그 파일. 트랜잭션 로그 파일

데이터 파일은 1개 이상으로 이루어질 수 있다.

그냥 1개로만 데이터 파일을 구성한다면 확장명 'mdf'를 사용하며, 
두 번째부터 추가된 데이터 파일을 확장명을 'ndf'로 쓰도록 하자.

로그 파일 역시 복수의 파일로 구성할 수 있으나, 로그 파일은 복수의 작은 파일들보다 1개의 큰 파일이 성능이 더 좋다.


2. 데이터베이스의 논리적 관점과 물리적 관점

SQLServer에서 데이터베이스의 논리적 관점(사용자 입장)과 
물리적 관점(SQLServer의 입장)을 표현하면, 아래 그림과 같을 수 있다.


물론 위 그림은 매우 단순화한 그림이지만, 
이를 통해 SQL문의 기본 동작 방식과 SQLServrer의 내부 저장 구조에 대해 이해할 수 있다.

데이터 파일(*.mdf 또는 *.ndf)에 저장되는 데이터들은 그냥 순차적으로 저장되는 것이 아니라,
위 그림과 같이 페이지(8 KB)라고 불리는 최소의 저장 단위에 저장된다
(Windows OS들은 페이지 단위가 4 KB인데 반해 SQLServer는 이보다 큰 8KB)

하나의 테이블이나 인덱스는 물리적으로 연속 8 페이지로 구성된 Extent(64KB)에 저장된다.

그리고 실제 내용인 행 데이터들은 각 페이지에 저장된다.
그래서 한 행의 최대 크기는 한 페이지 크기와 동일한 8KB가 된다.

헌데 VARCHAR(MAX), NVARCHAR(MAX), VARBINARY(MAX)의 최대 크기는 2^31 - 1 바이트이다.

이 녀석들이 8KB가 넘는 데이터를 저장하게 되면 SQLServer는
IAM(Index Allocation Map)이라 불리우는 페이지에 해당 데이터를 저장한다.

IAM 페이지는 할당 단위에 사용되는 데이터베이스 파일의 4GB 부분에 Extent를 매핑한다.
할당 단위의 유형은 아래 세 가지가 있다.
  • IN_ROW_DATA : 힙 또는 인덱스의 파티션을 포함
  • LOB_DATA : 데이터의 LOB(Large Object) 데이터 형식을 포함
  • ROW_OVERFLOW_DATA : 8KB의 행 크기 제한을 초과한 가변 길이의 데이터를 포함

지금까지의 자세한 내용은 MSDN의 페이지 및 익스텐트 아키텍트 페이지를 참고하자.
설명이 생각보다 잘 되어 있어, 개념 잡기에 나쁘지 않을 듯 하다.


3. SELECT문의 기본 동작 과정

이제 위 그림을 이용하여, SQLServer에서 SELECT 문을 처리하는 과정에 대해 살펴보자.
  1. 사용자는 (1) 논리적인 데이터베이스에 저장된 데이터를 조회하는 것처럼 보이지만,
  2. 내부적으로는 (3) 데이터 파일(*.mdf)에 저장되어 있는 페이지에서 데이터를 검색해서 가져온 후에
  3. (4) 사용자에게 조회한 결과를 출력해 준다.

여기서 로그 파일(*.ldf) 파일은 전혀 관련이 없다.

즉, SELECT 문은 로그 파일과 관계가 없는 것이다.


4. INSERT/UPDATE/DELETE의 기본 동작 방식

이번엔 SQLServer가 INSERT/UPDATE/DELETE를 처리하는 과정에 대해 살펴보자.
  1. 사용자는 (1) 논리적인 데이터베이스에서 데이터를 변경하는 것처럼 보이지만,
  2. 내부적으로는 우선 (2번) 로그 파일에 해당 처리 구문을 LSN, TransactionID와 함께 저장한다.
  3. 그리고 이후 (3) 데이터 파일의 페이지에 해당 내용을 변경한다.
  4. (4) 사용자에게 변경한 결과를 출력해 준다.
(2번 과정의 LSN은 Log Sequence Number의 약어이다)

여기에서 2번 과정(로그 파일 기록 과정)은 반드시 필요한 과정은 아니다.
즉, 데이터 변경에 대한 내용은 (2) 로그 파일에 쓰고 (3) 데이터 파일에 두 번 쓴 셈인데,
당연히 두 번 쓰니까 이는 시스템의 성능 저하를 유발시키는 측면이 있다.

또한, 로그 파일에 먼저 기록하고 나서, 데이터 파일에 수정이 일어나는데,
이를 WAL(Write-Ahead Logging : 미리 쓰기 로깅)이라고 한다.


5. (트랜잭션) 로그 파일의 역할

위에서 데이터를 변경하는 동작을 처리할 때 로그 파일에도 쓰고 데이터 파일에도 쓴다고 하였다.
이러한 성능 저하에도 불구, SQLServer가 로그 파일에 기록을 남기는 이유가 무엇일까?

이는 완전한 데이터(변경되거나 무효화되거나) 즉, 데이터베이스의 무결성을 위한 것이다.

DBMS의 가장 근본적인 목적 중 하나가 데이터베이스의 무결성이므로,
성능의 저하를 감수하고라도 로그 파일에도 기록을 남기는 과정을 거치는 것이다.

가장 흔한 예로 "게임의 아이템 거래"를 들 수 있다.
A가 B에게 "+10 일본도"를 거래창을 통해 건네준다고 가정해 보면, 기본적인 처리 흐름은 아래와 같을 것이다.
  1. B의 인벤에 "+10 일본도를 추가할 수 있는지 예외 처리
  2. B의 인벤에 "+10 일본도"를 삽입
  3. A의 인벤에서 "+10 일본도"를 제거
그런데, 만약 2번 과정까지만 정상적으로 처리되고, 정전이나 하드웨어 문제가 발생한다면 어떻게 될까?
B의 인벤에도 "+10 일본도"가 생기고, A의 인벤에서도 "+10 일본도"가 남아 있다면?

이런 일을 제대로 된 트랜잭션 처리 + 트랜잭션 로그 파일을 통해 막을 수 있다.
(제대로 된 트랜잭션 처리 = 2, 3번이 단일 트랜잭션으로 처리되는 것)

SQLServer는 트랜잭션 로그 파일을 사용함으로써, 다시 전기가 들어왔을 때...
  • B의 인벤에서 "+10 일본도"를 다시 제거하거나,
  • A의 인벤에서 "+10 일본도"를 제대로 제거해 주어야 한다.
물론 B의 인벤에서 "+10 일본도"가 제거된다면, A와 B는 다시 거래 과정을 거쳐야겠지만, 
고가의 아이템이 복사되는 대형 사고는 발생하지 않을 것이다.

이것이 바로 데이터베이스의 무결성이며, 이를 위해서 로그 파일을 사용하는 것이다.

위 예제 시나리오에서 인벤 처리 과정을 넣고 빼는 것이 아니라,
빼고 넣는 식이 되어 버리면, A의 인벤에서만 "+10 일본도"가 사라지는 마찬가지 대형 사고가 터지겠지...


포스트 공유하기

썸네일
수까락님의 글 구독하기
덧글 0 관련글(트랙백) 0
신고
맨 위로
앱으로 보기 배너 닫기

공유하기

주소복사

아래의 URL을 길게 누르면 복사할수있습니다.

http://sweeper.egloos.com/m/3003333
닫기

팝업

모바일기기에서만 이용이 가능합니다.
운영체제가 안드로이드, ios인
모바일 기기에서 이용해주세요.

덧글 삭제

정말 삭제하시겠습니까?

비밀번호 확인

게시글 신고하기

밸리 운영정책에 맞지 않는 글은 고객센터로
보내주세요.

신고사유


신고사유와 맞지 않을 경우 처리되지 않을 수 있습니다.
저작권 위반/명예훼손 등은 고객센터를 통해 권리침해
신고해주세요.
고객센터 바로가기