아키텍처의 기본
설계나 운용을 검토할 때, PostereSQL의 동작이나 구조를 알아 두는 것이 중요합니다. 적절한 사활 감시를 하기 위해서는 기동하고 있는 프로세스를 파악해 둘 필요가 있습니다. 또한, 메모리의 이용 용도나 파일의 배치 장소를 모르면, 이용 상황이나 부하를 추정할 수조차 없습니다. PostgreSQL 14를 기준으로 PostgreSQL의 아키텍처를 간단히 살펴보도록 하겠습니다.
「 프로세스 구성 」
RDBMS는, 쿼리의 처리뿐만 아니라, 버퍼 관리, 디스크 쓰기 제어, 통계 정보 수집 등 다양한 제어를 하고 있습니다.
PostgreSQL은, 복수의 프로세스를 동작시킴으로써, 복잡한 제어를 가능하게 하고 있습니다.
기동하고 있는 프로세스는 ps 커맨드로 확인할 수 있습니다. 각각 "postgres" 뒤에 이어지는 문자열이, 기동 중인 프로세스의 명칭입니다.
< ps 명령으로 본 PostgreSQL 프로세스 (PostgreSQL 14의 예) >
[root@postgresql ~]# ps -ef | grep postgres
root 831 1 0 01:08 ? 00:00:00 /sbin/dhclient -1 -q -lf /var/lib/dhclient/dhclient--eth0.lease -pf /var/run/dhclient-eth0.pid -H postgresql eth0
➊ postgres 1072 1 0 01:08 ? 00:00:00 /usr/pgsql-14/bin/postmaster -D /var/lib/pgsql/14/data/
➋ postgres 1130 1072 0 01:08 ? 00:00:00 postgres: logger
➌ postgres 1166 1072 0 01:08 ? 00:00:00 postgres: checkpointer
➍ postgres 1167 1072 0 01:08 ? 00:00:00 postgres: background writer
➎ postgres 1168 1072 0 01:08 ? 00:00:00 postgres: walwriter
➏ postgres 1169 1072 0 01:08 ? 00:00:00 postgres: autovacuum launcher
➐ postgres 1170 1072 0 01:08 ? 00:00:00 postgres: stats collector
➑ postgres 1171 1072 0 01:08 ? 00:00:00 postgres: logical replication launcher
root 1416 1401 0 01:10 pts/1 00:00:00 su - postgres
postgres 1417 1416 0 01:10 pts/1 00:00:00 -bash
postgres 1445 1417 0 01:10 pts/1 00:00:00 psql
➒ postgres 1446 1072 0 01:10 ? 00:00:00 postgres: postgres postgres [local] idle
root 1451 1358 0 01:10 pts/0 00:00:00 grep --color=auto postgres
➊마스터 서버, ➋로거(로그 출력 프로세스), ➌체크 포인터, ➍라이터, ➎WAL 라이터, ➏자동 베큠 런처, ➐통계 정보 콜렉터, ➑백그라운드 워커, ➒벡엔드 프로세스
【 마스터 서버 프로세스 】
PostgreSQL을 제어하는 다양한 프로세스(백그라운드 프로세스)나, 외부로부터의 접속에 대응하는 프로세스(백엔드 프로세스)를 기동 하는 부모 프로세스입니다.
【 라이터 프로세스 】
공유 버퍼 내의 업데이트된 페이지를, 해당 데이터 파일에 쓰는 프로세스입니다.
【 WAL 라이터 프로세스 】
WAL(Write Ahead Logging)을 디스크에 쓰는 프로세스입니다. WAL 라이터 프로세스는, WAL 버퍼에 기록된 WAL을 설정에 따라 WAL 파일에 씁니다.
【 체크 포인터 프로세스 】
체크 포인트(모든 더티 페이지를 데이터 파일에 반영하고, 특수한 체크 포인트 레코드가 로그 파일에 기록된 상태)를 설정에 따라, 자동으로 실행하는 프로세스입니다.
【 자동 베큠 런처와 자동 베큠 워커 프로세스 】
자동 베큠을 제어/실행하는 프로세스입니다. 런처는 설정에 따라 워커를 기동 합니다. 워커는 테이블에 대해 자동으로 베큠과 분석 실행을 실행합니다. 실행하기 전에, 대상 테이블에 대량의 갱신(Insert, Update, Delete)이 있었는지 여부를(통계 정보 콜렉터를 이용하여 수집되는) 통계 정보를 참조하여 검사합니다.
【 통계 정보 콜렉터 프로세스 】
데이터베이스의 활동 상황에 관한 가동 통계 정보를 일정 간격으로 수집하는 프로세스입니다. 수집된 가동 통계 정보는 PostgreSQL의 감시 등으로 사용됩니다.
【 백엔드 프로세스 】
클라이언트에서 접속 요청을 받았을 때 생성되는 프로세스입니다. 쿼리 실행은, 이 백엔드 프로세스 내에서 이루어집니다. 쿼리, 결과 송수신 등은, 클라이언트와 이 백엔드 프로세스 사이에서 이루어집니다.
【 병렬 워커 프로세스 】
병렬 쿼리가 실행될 때, 백엔드 프로세스에서 기동 되는 프로세스입니다.
「 메모리 관리 」
PostgreSQL에서 사용되는 메모리는, PostgreSQL 서버 프로세스 전체에서 공유되는 공유 메모리 영역과, 백엔드 프로세스에서 확보되는 프로세스 메모리 영역의 2가지로 구별됩니다.
【 공유 메모리 영역 】
공유 메모리 영역은, 백그라운드 프로세스와 백엔드 프로세스 모두에서 참조나 업데이트되는 공유 영역입니다. 이 영역은, 서버 기동 시 OS의 시스템 콜에 의해 예약됩니다. 또한, PostgreSQL의 기동 시에는, PostgreSQL의 설정 파라미터(shared_buffers)의 값과, 리눅스의 커널 파라미터(shmmax)의 값을 비교하고, shmmax보다 shared_buffers의 값이 큰 경우에는 에러 메시지가 출력됩니다.
PostgreSQL은, 공유 메모리 영역을 다음과 같은 영역으로 나누어 이용합니다.
[ 공유 버퍼(shared_buffers) ]
테이블이나 인덱스의 데이터를 캐시 하는 영역입니다.
[ WAL 버퍼(wal_buffers) ]
디스크에 기록되지 않은 트랜잭션 로그(WAL:Write Ahead Logging)를 캐시 하는 영역입니다.
[ 프리 스페이스 맵(Free Space Map) ]
테이블상의 이용 가능한 영역을 가리키는 정보를 취급하는 영역입니다. PostgreSQL에서는, 유지보수 처리(베큠 처리) 시 트랜잭션에서 전혀 참조되지 않은 행을 찾아, 빈 공간으로 재사용을 가능하게 합니다. 추가나 업데이트 시, 프리 스페이스 맵을 탐색하고, 재사용 가능한 영역에 새로운 행을 삽입합니다.
[ 가시성 맵(Visibility Map) ]
테이블의 데이터가 가시인지 아닌지를 관리하는 정보를 취급하는 영역입니다. 베큠 처리의 고속화를 위해, 처리가 필요한 페이지인지 아닌지를 가시성 맵에서 판단합니다. 또한, Index Only Scan이라는 고속 검색 방식으로도 사용되고 있습니다. 가시성 맵의 정보는 베큠 처리나 각 갱신 처리 타이밍에 다시 작성됩니다. 또한, 프리 스페이스 맵을 참조 하여, 베큠 처리의 고속화에도 사용됩니다.
【 프로세스 메모리 】
백엔드 프로세스마다 확보되는 작업용 메모리 영역입니다. 메모리 영역을 확보한 프로세스만 참조 가능하며, 다음과 같이 분류됩니다.
[ 작업 메모리(work_mem) ]
쿼리 실행 시에 행해지는, 정렬과 해시 테이블 조작을 위해 사용되는 영역입니다. 정렬이나 해시 테이블 조작을 포함한 쿼리의 경우, 작업 메모리를 적절히 설정함으로써 성능 향상을 기대할 수 있습니다. 하나의 쿼리 중에서, 이러한 조작이 여러 번 이루어지는 경우에는, 해당 처리마다 설정한 영역이 확보됩니다. 이 때문에, 매우 많은 백엔드 프로세스가 기동 하는 상황에서, 작업 메모리에 큰 값을 설정하면, 시스템 전체의 메모리를 압박할 가능성이 있습니다.
[ 유지보수용 작업 메모리(maintenance_work_mem) ]
베큠, 인덱스 작성, 외부 키 추가 등의 데이터베이스 유지보수 조작으로 사용하는 영역입니다. 통상 운용에서는, 이러한 조작이 동시에 다수 발생하지 않고, 유지보수 시간 단축을 목표로 한다면, work_mem보다 큰 값을 설정하는 것이 좋습니다.
[ 임시 버퍼(temp_buffers) ]
백엔드 프로세스마다 작성되는 임시 테이블에 액세스 할 때 사용되는 메모리 영역입니다. 임시 테이블은, CREATE TEMP TABLE 명령으로 작성할 수 있습니다.
「 파일 」
PostgreSQL에서 사용되는 파일의 대부분은, 데이터베이스 클러스터라고 불리는 디렉터리 아래에 작성됩니다. 데이터베이스 클러스터는, initdb 커맨드 또는 pg_ctl 명령을 사용하여, 실행한 OS 유저만 접근 가능한 권한(700)을 가지고 있습니다.
아래 예시와 같이 PostgreSQL은, 기동 시 데이터베이스 클러스터의 액세스 권한을 체크하고, 700 이외의 경우는 오류 메시지를 출력합니다.
< 데이터베이스 클러스터 디렉터리의 권한 체크 동작 확인 >
[root@postgresql ~]# su - postgres
Last login: Tue Oct 10 07:14:53 UTC 2023 on pts/1
-bash-4.2$ initdb --no-locale --encoding=utf8 -U postgres -D /tmp/tmpdir
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "C".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /tmp/tmpdir ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
pg_ctl -D /tmp/tmpdir -l logfile start
-bash-4.2$ ls -rlt /tmp/
total 1
drwx------. 19 postgres postgres 4096 Oct 10 07:17 tmpdir
-bash-4.2$ chmod 744 /tmp/tmpdir/
-bash-4.2$ ls -rlt /tmp/
total 1
drwxr--r--. 19 postgres postgres 4096 Oct 10 07:17 tmpdir
-bash-4.2$ pg_ctl -D /tmp/tmpdir start
waiting for server to start....2023-10-10 07:19:16.786 UTC [3107] FATAL: data directory "/tmp/tmpdir" has invalid permissions
2023-10-10 07:19:16.786 UTC [3107] DETAIL: Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).
stopped waiting
pg_ctl: could not start server
Examine the log output.
-bash-4.2$ chmod 700 /tmp/tmpdir/
-bash-4.2$ pg_ctl -D /tmp/tmpdir start
waiting for server to start....2023-10-10 07:25:23.348 UTC [3151] LOG: redirecting log output to logging collector process
2023-10-10 07:25:23.348 UTC [3151] HINT: Future log output will appear in directory "log".
done
server started
-bash-4.2$
또한, 데이터베이스 클러스터에는 아래와 같이 다양한 디렉터리나 파일이 만들어집니다.
< 데이터베이스 클러스터 내의 구성 >
-bash-4.2$ ls -rlt base
total 48
drwx------. 2 postgres postgres 6 Sep 22 05:19 pgsql_tmp
drwx------. 2 postgres postgres 8192 Oct 10 07:43 19131
drwx------. 2 postgres postgres 8192 Oct 10 07:43 14485
drwx------. 2 postgres postgres 8192 Oct 10 07:43 1
drwx------. 2 postgres postgres 8192 Oct 10 07:43 14486
-bash-4.2$ ls -rlt
total 72
-rw-------. 1 postgres postgres 3 Sep 14 04:31 PG_VERSION
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_twophase
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_tblspc
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_snapshots
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_serial
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_replslot
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_notify
drwx------. 4 postgres postgres 36 Sep 14 04:31 pg_multixact
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_dynshmem
drwx------. 2 postgres postgres 6 Sep 14 04:31 pg_commit_ts
-rw-------. 1 postgres postgres 88 Sep 14 04:31 postgresql.auto.conf
-rw-------. 1 postgres postgres 1636 Sep 14 04:31 pg_ident.conf
drwx------. 2 postgres postgres 18 Sep 14 04:31 pg_xact
-rw-------. 1 postgres postgres 28742 Sep 14 05:39 postgresql.conf
-rw-------. 1 postgres postgres 4607 Sep 14 05:50 pg_hba.conf
drwx------. 2 postgres postgres 18 Oct 4 22:55 pg_subtrans
drwx------. 3 postgres postgres 4096 Oct 5 06:05 pg_wal
drwx------. 7 postgres postgres 71 Oct 7 15:41 base
drwx------. 2 postgres postgres 188 Oct 9 00:00 log
drwx------. 4 postgres postgres 68 Oct 10 07:42 pg_logical
-rw-------. 1 postgres postgres 30 Oct 10 07:42 current_logfiles
-rw-------. 1 postgres postgres 27 Oct 10 07:42 postmaster.opts
-rw-------. 1 postgres postgres 95 Oct 10 07:42 postmaster.pid
drwx------. 2 postgres postgres 6 Oct 10 07:42 pg_stat
drwx------. 2 postgres postgres 4096 Oct 10 07:43 global
drwx------. 2 postgres postgres 122 Oct 10 07:45 pg_stat_tmp
【 주요 디렉터리 】
[ base 디렉토리 ]
데이터베이스마다, 식별자(oid:Object ID)를 나타내는 숫자 디렉터리(데이터베이스 디렉터리)가 만들어집니다. 데이터베이스 디렉터리는, base 디렉터리 아래에 저장되어, 테이블 파일, 인덱스 파일, TOAST 파일, Free Space Map 파일, Visibility Map 파일과 같은 파일을 저장합니다.
[ global 디렉토리 ]
데이터베이스 클러스터에서 공유하는 테이블을 가지고 있는 디렉터리입니다. 이 디렉터리에는 pg_database 등 여러 데이터베이스에 걸친 시스템 카탈로그 등이 저장되어 있습니다.
[ pg_wal 디텍토리 ]
WAL 파일을 저장하는 디렉터리입니다. 데이터베이스 클러스터 작성 시의 옵션에 따라서는, 심볼릭 링크가 되는 경우도 있습니다.
[ pg_xact 디렉터리 ]
트랜잭션의 커밋 상태를 관리하는 파일이 저장되는 디렉터리입니다.
[ pg_tblspc 디렉터리 ]
PostgreSQL에서는, 테이블이나 인덱스 등의 데이터베이스 오브젝트를 base 디렉터리 이외의 임의의 디렉터리(테이블 공간)에 저장할 수 있습니다. 테이블 공간으로 작성된 디렉터리에 대한 심볼릭 링크를 pg_tblspc 디렉터리에 저장합니다.
【 주요 파일 】
[ PG_VERSION 파일 ]
PostgreSQL의 메이저 버전 번호가 기록되어 있는 텍스트 파일로, cat 커맨드 등으로 확인할 수 있습니다. 버전 14의 데이터베이스 클러스터 아래에 생성되는 PG_VERSION 파일은 아래와 같습니다.
< PG_VERSION 파일 (버전 14의 경우) >
-bash-4.2$ cat PG_VERSION
14
이 파일은, 기동 하는 PostgreSQL의 메이저 버전과 사용하는 데이터베이스 클러스터의 버전 체크를 위해 사용됩니다.
PostgreSQL에서는, 다른 메이저 버전 간에는 데이터베이스 클러스터의 호환이 되지 않습니다. 무리하게 기동 하면, 데이터베이스 클러스터 내에 작성되는 파일이나 파일 포맷이 다르기 때문에, 예상치 못한 오동작이 발생할 가능성이 있습니다. 이러한 오동작을 방지하기 위해 기동한 PostgreSQL 버전과 지정한 데이터베이스 클러스터 아래의 PG_VERSION 파일의 값을 비교하여, 메이저 버전이 다른 경우에는 기동 하지 않도록 하고 있습니다.
[ 테이블 파일 ]
테이블 데이터의 실제 데이터가 저장되어 있는 파일로, 데이터베이스 디렉터리 아래에 저장됩니다. 테이블 파일은, 복수의 8192바이트의 페이지로 구성되어 있습니다.
[ 인덱스 파일 ]
검색 성능을 향상하기 위한 인덱스 정보가 저장되어 있습니다. 이 파일도 테이블 파일과 마찬가지로, 8192바이트의 "페이지"라는 단위로 구성되어, 데이터베이스 디렉터리 아래에 저장됩니다.
[ TOAST 파일 ]
테이블 내에 방대한 행(보통은 2KB를 넘는 크기)을 저장하는 경우에 생성되는 특수한 파일로, 데이터베이스 디렉터리 아래에 저장됩니다. 매우 긴 데이터를 저장하는 열이나 대량의 열을 가진 행이 있는 경우, TOAST 파일에 분할되어 저장됩니다. 테이블의 저장 영역에는, TOAST용 oid가 저장됩니다.
[ Free Space Map 파일 ]
빈 공간을 추적하기 위한 정보가 저장된 파일로, 데이터베이스 디렉터리 아래에 저장됩니다. 이 파일은 테이블 및 인덱스에 생성되어, "테이블 및 인덱스를 나타내는 숫자_fsm"이라는 이름으로 저장됩니다.
[ Visibility Map 파일 ]
테이블의 가시성을 관리하는 파일로, "테이블을 나타내는 숫자_vm"이라는 이름으로 데이터베이스 디렉터리 아래에 저장됩니다.
[ WAL 파일 ]
PostgreSQL에 대해 행해진 갱신 조작을 기록하는 파일이며, pg_wal 디렉터리 아래에 저장됩니다. 데이터베이스의 지속성을 보장하거나 복구할 때 매우 중요한 역할을 합니다. WAL 파일은 고정 길이의 파일입니다. initdb 유틸리티(또는 pg_ctl 유틸리티의 init 서브 커맨드) 실행 시 크기를 지정합니다. 디폴트는 16MB로 작성됩니다. WAL 파일들은, 기준으로 max_wal_size로 설정한 크기로 생성됩니다.
[ Postgresal.cont, pg_hba.conf ]
PostgreSQL의 동작을 설정하는 파일입니다.
[ Postmaster.pid ]
PostgreSQL 가동 중에 작성되는 Lock 파일로, 데이터베이스 클러스터 아래에 저장됩니다. 이 파일이 존재할 때, 같은 데이터베이스 클러스터를 지정하고 PostgreSQL을 시작하면 이중 기동 에러가 발생합니다.