SQL- 데이터베이스 아키텍처

박현·2022년 11월 12일
0

SQL

목록 보기
32/34

데이터베이스 구조 (Oracle)

: DBMS마다 데이터베이스에 대한 정의가 조금씩 다르다. Oracle에서는 디스크에 저장된 데이터 집합을 데이터베이스라고 부른다. 그리고 SGA공유메모리영역과 이를 액세스하는 프로세스 집합을 합쳐서 인스턴스라고 부른다.

기본적으로 하나의 인스턴스가 하나의 데이터베이스만 액세스하지만 RAC환경에서는 여러 인스턴스가 하나의 데이터베이스를 액세스할 수 있다. 하나의 인스턴스가 여러 데이터베이스를 액세스할 수는 없다.


프로세스

SQL Server는 쓰레드 기반 아키텍처이므로 프로세스 대신 쓰레드라는 표현을 써야 한다. Oracle도 윈도우 버전에선 쓰레드를 사용하지만, 프로세스와 일일이 구분하면서 설명하려면 복잡해지므로 프로세스로 통칭하기로 한다.

프로세스는 서버프로세스와 백그라운드 프로세스 집합으로 나뉜다. 서버프로세스는 전면에서 사용자로부터 전달받은 각종 명령을 처리하고, 백그라운드 프로세스는 뒤에서 묵묵히 할당받은 역할을 수행한다.

1. 서버프로세스

: 서버프로세스는 사용자 프로세스와 통신하면서 사용자의 각종 명령을 처리한다. 좀 더 구체적으로 말하여 SQL을 파싱하고 필요하면 최적화를 수행한다.

  • 커서를 열어 SQL을 실행하면서 블록을 읽어 이 데이터를 정렬해 클라이언트가 요청한 결과 집합을 만들어 네트워크를 통해 전송하는 일련의 작업을 모두 서버프로세스가 처리해 준다.

클라이언트가 서버프로세스와 연결하는 방식은 DBMS마다 다르지만 Oracle을 예로 들면 전용서버방식과 공유서버방식 두가지가 있다.

1) 전용서버 방식

위의 사진을 보면 전용서버방식으로 접속할 때 내부적으로 어떤 과정을 거쳐 세션을 수립하고 사용자 명령을 처리하는지 잘 보여준다.

처음 연결요청을 받는 리스너가 서버프로세스를 생성해주고 이 서버 프로세스가 단 하나의 사용자 프로세스를 위해 전용 서비스를 제공한다는 점이 특징이다.

만약 SQL을 수행할 때마다 연결요청을 반복하면 서버 프로세스의 생성과 해제도 반복하게 되므로 DBMS에 매우 큰 부담을 주고 성능을 크게 떨어뜨린다. 따라서 전용서버 방식을 사용하는 OLTP성 어플리케이션에선 Connection Pooling 기법을 필수적으로 사용해야 한다.

2) 공유서버 방식

공유서버방식은 말 그대로 하나의 서버 프로세스를 여러 사용자 세션이 공유하는 방식이다. 앞에서 설명한 Connection Pooling기법을 DBMS내부에 구현해놓은 것으로 생각하면 쉽다. 즉 미리 여러개의 서버프로세스를 띄어 놓고 이를 공유해 반복 재사용한다.

2. 백그라운드 프로세스


데이터 저장 구조

1. 데이터 파일

Oracle과 SQL Server 모두 물리적으로는 데이터 파일에 데이터를 저장하고 관리한다. 공간을 할당하고 관리하기 위한 논리적인 구조도 크게 다르지 않지만 약간의 차이는 있다.

1) 블록 (= 페이지)

대부분 DBMS에서 I/O는 블록단위로 이뤄진다. 데이터를 읽고 쓸 때의 논리적인 단위가 블록이다. Oracle은 2,4,8,16,32KB의 다양한 블록크기를 사용할 수 있다.
블록단위로 I/O한다는 것은, 하나의 레코드에서 하나의 컬럼만을 읽으려 할 때도 레코드가 속한 블록 전체를 읽게 됨을 뜻한다. SQL성능을 좌우하는 가장 중요한 성능지표는 액세스하는 블록개수이며 옵티마이저의 판단에 가장 큰 영향을 미치는 것도 액세스해야 할 블록개수이다.

2) 익스텐트(Extent)

테이블스페이스로부터 공간을 할당하는 단위를 익스텐트라고 한다.

3) 세그먼트

테이블, 인덱스, Undo처럼 저장공간을 필요로 하는 데이터베이스 오브젝트다. 저장공간을 필요로 한다는 것은 한개 이상의 익스텐트를 사용함을 뜻한다.
한 세그먼트는 자신이 속한 테이블스페이스 내 여러 데이터 파일에 걸쳐 저장될 수 있다. 즉 세그먼트에 할당된 익스텐트가 여러 데이터 파일에 흩어져 저장되는 것이며 그래야 디스크 경합을 줄이고 I/O 분산 효과를 얻을 수 있다.

4) 테이블스페이스

세그먼트를 담는 컨테이너로서, 여러 데이터 파일로 구성된다.
사용자는 세그먼트를 위한 테이블스페이스를 지정할 뿐, 실제 값을 저장할 데이터 파일을 선택하고 익스텐트를 할당하는 것은 DBMS의 몫이다.
각 세그먼트는 정확히 한 테이블스페이스에만 속하지만 한 테이블스페이스에는 여러 세그먼트가 존재할 수 있다. 특정 세그먼트에 할당된 모든 익스텐트는 해당 세그먼트와 관련된 테이블스페이스내에서만 찾아진다. 한 세그먼트가 여러 테이블 스페이스에 걸쳐 저장될 수는 없다.
하지만 앞서 말했듯이 한 세그먼트가 여러 데이터 파일에 걸쳐 저장될 수는 있다. 한 테이블스페이스가 여러 데이터파일로 구성되기 때문이다.
사진으로 요약하면 아래와 같다.

2. 임시데이터 파일

임시데이터 파일은 특별한 용도로 사용된다. 대량의 정렬이나 해시작업을 수행하다가 메모리공간이 부족해지면 중간 결과 집합을 저장하는 용도다.
임시데이터파일에 저장되는 오브젝트는 말 그대로 임시로 저장했다가 자동으로 삭제된다. Redo 정보를 생성하지 않기 때문에 나중에 파일에 문제가 생겼을 때 복구되지 않는다. 따라서 백업할 필요도 없다.
Oracle에선 임시테이블스페이스를 여러개 생성해두고 사용자마다 별도의 임시 테이블스페이스를 지정해 줄 수도 있다.

3. 로그파일

DB버퍼캐시에 가해지는 모든 변경사항을 기록하는 파일을 Oracle에서는 Redo로그 라고 부른다.
대부분 DBMS는 버퍼블록에 대한 변경사항을 건건이 데이터파일에 기록하기보다 우선 로그파일에 Append방식으로 빠르게 기록하는 방식을 사용한다. 그러고 나서 버퍼블록과 데이터파일간 동기화는 적절한 수단을 이용해 나중에 배치방식으로 일괄처리한다.

◽️ ONnline Redo 로그

  • 트랜잭션 데이터의 유실에 대비하기 위해 Oracle은 Online Redo로그를 사용한다. 마지막 체크포인트 이후부터 사고발생 직전까지 수행됐던 트랜잭션들을 Redo로그를 이용해 재현하는 것이며 이를 캐시복구라고한다.
  • Online Redo 로그는 최소 두개 이상의 파일로 구성된다. 현재 사용중인 파일이 꽉 차면 다음 파일로 로그스위칭이 발생하며 계속 로그를 써 나가다가 모든 파일이 꽉 차면 다시 첫번째 파일부터 재사용하는 라운드로빈방식을 사용한다.

◽️ 트랜잭션 로그

  • Oracle의 Online Redo 로그와 대응되는 SQL Server의 로그파일이다.
    트랜잭션 로그파일은 내부적으로 가상로그파일이라 불리는 더 작은 단위의 세그먼트로 나뉘며, 이 가상로그파일의 개수가 너무 많아지지 않도록 옵션을 지정하는 게 좋다.

◽️ Archived(=Offline) Redo 로그

  • Oracle에서 Online Redo 로그가 재사용되기 전에 다른 위치로 백업해 둔 파일을 말한다.
  • 디스크가 깨지는 등 물리적인 저장매체에 문제가 생겼을때 데이터베이스 복구를 위해 사용된다.

메모리 구조

메모리 구조는 시스템 공유 메모리 영역과 프로세스 전용 메모리 영역으로 구분된다.

◽️ 시스템 공유 메모리 영역
말 그대로 여러 프로세스가 동시에 액세스할 수 있는 메모리 영역으로서, Oracle에선 SGA라고 부른다.

  • 여러프로세스에 공유되기 때문에 내부적으로 래치, 버퍼 LOCK, 라이브러리캐시 Lock/Pin 같은 액세스 직렬화 메커니즘이 사용된다.

◽️ 프로세스 전용 메모리 영역

  • Oracle은 프로세스 기반 아키텍처이므로 서버프로세스가 자신만의 전용 메모리 영역을 가질 수 있다. 이를 PGA라고 부르며 데이터를 정렬하고 세션과 커서에 관한 상태정보를 저장하는 용도로 사용한다.

1. DB 버퍼 캐시

: 데이터 파일로부터 읽어들인 데이터블록을 담는 캐시영역이다.
인스턴스에 접속한 모든 사용자 프로세스는 서버 프로세스를 통해 DB 버퍼 캐시의 버퍼블록을 동시에 액세스할 수 있다.

1) 버퍼블록의 상태
모든 버퍼블록은 아래 세가지 중 하나의 상태에 놓인다.

  • Free 버퍼
    : 인스턴스 기동 후 아직 데이터가 읽히지 않아 비어 있는 상태이거나 데이터가 담겼지만 데이터 파일과 서로 동기화돼 있는 상태여서 언제든지 덮어 써도 무방한 버퍼블록을 말한다.

  • Dirty 버퍼
    : 버퍼에 캐시된 이후 변경이 발생했지만 아직 디스크에 기록되지 않아 데이터 파일블록과 동기화가 필요한 버퍼블록을 말한다.

  • Pinned 버퍼
    : 읽기 또는 쓰기 작업이 현재 진행중인 버퍼블록을 말한다.

2) LRU 알고리즘
: 모든 DBMS는 사용빈도가 높은 데이터 블록 위주로 버퍼 캐시가 구성되도록 LRU알고리즘을 사용한다.

  • 모든 버퍼 블록 헤더를 LRU체인에 연결해 사용빈도 순으로 위치를 옮겨가다가, Free버퍼가 필요해질 때면 액세스 빈도가 낮은 쪽 데이터블록부터 밀어내는방식이다.

2. 공유 풀

: 공유 풀은 딕셔너리 캐시와 라이브러리 캐시로 구성되며 버퍼 캐시처럼 LRU알고리즘을 사용한다.

  • 딕셔너리 캐시
    : 테이블, 인덱스같은 오브젝트는 물론 테이블스페이스, 데이터파일, 세그먼트, 익스텐트, 사용자, 제약에 관한 메타정보를 저장하는 곳이다.
    딕셔너리 정보를 캐싱하는 메모리 영역이다.

  • 라이브러리 캐시
    : 사용자가 수행한 SQL문과 실행계획, 저장프로시저를 저장해 두는 캐시영역이다.
    같은 SQL에 대한 반복적인 하드파싱을 최소회하기 위한 캐시공간을 따로 두게 됐고 그것이 라이브러리캐시영역이다.
    캐싱된 SQL과 그 실행계획의 재사용성을 높이는 것은 SQL 수행성능을 높이고 DBMS 부하를 최소화하는 핵심원리 중 한가지다.

3. 로그 버퍼

로그 엔트리도 파일에 곧바로 기록하는 것이 아니라 먼저 로그버퍼에 기록한다.
서버프로세스가 데이터 블록버퍼에 변경을 가하기 전에 Redo 로그 버퍼에 먼저 기록해 두면 주기적으로 LGWR프로세스가 Redo로그파일에 기록한다.
로그파일에 기록했음이 보장돼야 안심하고 커밋을 완료할 수 있다.

4. PGA

각 Oracle서버프로세스는 자신만의 PGA메모리영역을 할당받고 이를 프로세스에 종속적인 고유 데이터를 저장하는 용도로 사용한다.
PGA는 다른프로세스와 공유되지 않는 독립적은 메모리 공간으로서, 래치메커니즘이 필요 없어 똑같은 개수의 블록을 읽더라도 SGA 버퍼 캐시에서 읽는 것보다 빠르다.

  • User Global Area (UGA)
    : 전용서버방식으로 연결할 때는 프로세스와 세션이 1:1 관계를 갖지만 공유서버방식으로 연결할때는 1:M관계를 갖는다.
    각 세션을 위한 독립적인 메모리 공간이 필요한데 이를 UGA라고 한다.
    UGA는 전용서버방식으로 연결할때는 PGA에 할당되고 공유서버방식으로 연결할때는 SGA에 할당된다.

  • Call Global Area (CGA)
    : CGA는 Parse Call, Execute Call, Fetch Call마다 매번 할당받는다. CGA에 할당된 공간은 하나의 Call이 끝나자마자 해제돼 PGA로 반환된다.

  • Sort Area
    : 데이터 정렬을 위해 사용되는 Sort Area는 소트오퍼레이션이 진행되는 동안 공간이 부족해질 때마다 청크단위로 조금씩 할당된다.


참고자료 : SQL전문가가이드

0개의 댓글