4. 기동 · 정지 운영
이 장을 마치면: 상황에 맞는 기동 방식과 정지 방식을 고르고, 비정상 종료 뒤 안전하게 다시 띄운다.
4.1 기동 순서 · 완료 판정
기동 명령과 예상 출력은 QuickStart 4.1에 있다. gritdb-start는 아래 단계를 차례로 밟는다.
| 순서 | 단계 | log/grit_admin_main.log의 단계 이름 |
시한 |
|---|---|---|---|
| 1 | 감독 프로세스 준비 | BeginStart, StartChannelServer, PostgreSQLRecoveryPrep |
— |
| 2 | PostgreSQL 기동 | LaunchPostgreSQL |
— |
| 3 | 시스템 테이블 준비 | PostgreSQLAwaitSystemTableReady |
60초(비정상 종료 뒤에는 없음) |
| 4 | GritDB 카탈로그 기동 | LaunchCatalog |
60초 |
| 5 | GritDB 엔진 기동 | LaunchEngine |
30초 |
| 6 | GritDB 엔진 복구(못 받은 변경을 WAL에서 이어받는다) | PostgreSQLEngineRecovery |
없음 |
| 7 | 내부 작업자 준비 | AwaitBgwReady |
60초 |
| 8 | 따라잡기 | PostgreSQLStartSyncWatermark |
없음 |
| 9 | 접속 허용 | OpenSessionGate |
— |
-
시한을 넘기면 기동이 실패하고 GritDB가 스스로 내려간다. 이때는 QuickStart GDB-BOOT-005를 본다.
-
시한이 없는 단계는 GritDB 엔진 복구, 따라잡기, 비정상 종료 뒤의 PostgreSQL 복구다. 이 동안
gritdb-stop은 GritDB를 멈추지 않는다(4.2). 감독 프로세스는 받은kill(SIGTERM)을 기동이 끝난 뒤 즉시 정지로 처리한다. -
gritdb-start는 끝날 때까지 출력 없이 기다린다. 데이터가 적어도 약 30초 걸리므로 중간에 끊지 않는다. -
진행을 보려면 다른 터미널에서 아래 명령을 실행한다. 지금 단계 이름이 나온다.
grep 'GritAdminPhaseRunner: ===' ~/gritdb1/log/grit_admin_main.log | tail -1 -
GritDB started successfully는 접속 허용(9단계) 뒤에 나온다. 이 줄이 보이면 바로 접속할 수 있다.
기동 중에 접속하면 아래 문구로 거부된다. 이때는 기다린다.
| 문구 | 뜻 |
|---|---|
GritSurfer is not accepting connections |
GritDB가 아직 접속을 허용하지 않았다 |
the database system is starting up, the database system is not yet accepting connections |
PostgreSQL이 기동 중이거나 복구 중이다 |
Connection refused |
PostgreSQL이 아직 포트를 열지 않았다 |
pg_isready로 보면rejecting connections나no response가 나온다.
기동을 확인한다. 20초 뒤 한 번 더 실행해 기동 직후 내려가는 경우를 잡는다.
~/gritdb1/bin/pg_isready -p 5432 -d postgres
pg_isready가 두 번 모두accepting connections를 내면 정상이다.-d postgres를 붙이면 서버 로그에 접속 실패 줄이 남지 않는다.
기동하는 셸:
-
PG로 시작하는 환경 변수와LD_LIBRARY_PATH가 없는 셸에서 기동한다. 기동한 셸의 환경이 GritDB 프로세스로 넘어간다.env | grep -E '^(PG|LD_LIBRARY_PATH)'출력이 없으면 정상이다.
-
TMPDIR을 1.9의 10번에서 정했으면 기동할 때마다 같은 값을 준다(1.4 ④). 서비스 계정의~/.profile에export TMPDIR=<디렉토리>한 줄을 두면 손으로 기동할 때 빠뜨리지 않는다. 부팅 때 기동은 4.6의Environment=TMPDIR을 쓴다.echo "${TMPDIR:-/tmp}"를 실행해 정한 값이 나오는지 확인한다.- 설치 스크립트의
TMPDIR은 실행할 수 있는 디렉토리여야 한다(1.4 ④). 그래서 그 디렉토리가noexec이면 설치할 때만 다른 값을 준다.
- 설치 스크립트의
-
기동 명령을 겹쳐 실행하지 않는다. 화면 출력 로그(
log/grit_admin_stdout.log)가 비워질 수 있다. -
1.1에는 운영에 쓰는
gritdb-start옵션이 없다. 명령과 옵션 전체는 A.1에 있다.
4.2 정지 방식 · 걸리는 시간
| 방식 | 명령 | 동작 |
|---|---|---|
| 정상 정지 | gritdb-stop |
실행 중인 문장이 끝나기를 최대 300초 기다린 뒤 정지한다. 열린 세션(쉬는 세션 포함)이 남아 있으면 약 30초 뒤 즉시 정지로 넘어간다. 이때 core 파일이 생길 수 있고(9.6), 다음 기동은 복구 과정을 거친다. 정지 전에 남은 세션을 끊는다(아래) |
| 즉시 정지 | gritdb-stop --quick |
진행 중 작업을 끊고 정지한다. 다음 기동 때 복구 과정을 거친다. ⚠ GritDB 엔진 core 파일(수십 GB)이 생길 수 있다. 자세한 것은 9.6을 본다 |
- 정상 정지는 PostgreSQL을 Smart Shutdown(SIGTERM)으로 내린다. 즉시 정지는 Immediate Shutdown(SIGQUIT)으로 내린다.
- 화면에
[WARN] Client command failed: …,[WARN] Falling back to direct signal...,[INFO] Sending SIGTERM to GritAdmin이 나오면 정상 정지 명령이 닿지 않아 즉시 정지로 내려갔다는 뜻이다. 이때 다음 기동은 복구 경로다(4.3의 5번,ABNORMAL_RESTART). - 정상 정지는 세션이 없을 때 약 1분 걸린다. 즉시 정지는 약 10~15초 걸린다. 단계 시한을 다 쓰면 정지에 최대 약 11분 걸린다.
정지 완료 판정에서는 아래가 모두 맞아야 한다. 화면의 GritDB stopped.만으로 판정하지 않는다. 기동 중에도 이 줄이 나오기 때문이다.
-
프로세스가 0개다. QuickStart 4.5의 정지 확인을 실행해 출력이 없는지 확인한다.
-
상태 파일과 잠금
ls ~/gritdb1/run/ cat ~/gritdb1/run/grit_admin_clean_shutdown flock -n ~/gritdb1/run/gritdb.lock true && echo "잠금 풀림 = 정지"ls에grit_admin.pid와grit_admin.sock이 없고 마지막 줄이잠금 풀림 = 정지면 정상이다.- 정상 정지였으면
cat이CLEAN_SHUTDOWN을 낸다. 즉시 정지나 비정상 종료 뒤에는 이 파일이 없다.
남은 세션 끊기는 정지하기 전에 한다. 정지가 시작되면 새 접속은 막히지만, 열린 세션은 계속 SQL을 쓴다.
- 응용 프로그램, 리포트, BI 도구, CDC 도구, ETL 도구를 멈춘다.
~/gritdb1/bin/psql -p 5432 -d postgres로 접속해 아래 쿼리를 실행한다.- 같은 쿼리를 다시 실행해 0행인지 본다.
~/gritdb1/bin/gritdb-stop을 실행한다.
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE backend_type = 'client backend' AND pid <> pg_backend_pid()
AND application_name NOT LIKE 'gritdb\_catalog\_%';
gritdb_catalog_로 시작하는 접속은 GritDB 내부 접속이므로 끊지 않는다.- 끊지 않고 정지하면 화면 끝에
[WARN] Client command failed: ERROR stop failed …와[WARN] Falling back to direct signal...이 나온다. 이 두 줄은 즉시 정지로 내려갔다는 뜻이다. 이때는 정상 정지 표식인run/grit_admin_clean_shutdown이 없고, 다음 기동이 복구 과정을 거친다(4.3). - 함수와 뷰:
pg_terminate_backend,pg_stat_activity
정지 중이나 기동 중의 정지 명령:
- 정상 정지가 진행 중일 때 다른 터미널에서
gritdb-stop --quick을 실행해도 끼어들지 못한다. 이 명령은 앞의 정지가 끝날 때까지 기다린다. - 기동 중에는
gritdb-stop이 GritDB를 멈추지 않는다. PID 파일이 아직 없어(GritAdmin PID file not found) 아무것도 보내지 않는다. 화면에는GritDB stopped.가 나오지만, 기동이 끝난 뒤에도 GritDB는 계속 돈다. 그래서 기동이 끝난 뒤 다시 정지한다. 기동 중에 정지 명령을 낸 화면에는POSIX shared memory segments remaining …과Remove them manually only when no GritDB process is running경고도 나온다. 이 공유 메모리는 기동 중인 GritDB가 쓰므로 지우지 않는다(QuickStart GDB-SHUTDOWN-001의 판별). 기동 중인지는 4.5의 “기동 중”을 본다. - 급히 내려야 하면 처음부터
gritdb-stop --quick을 쓴다.
자동화:
-
gritdb-stop에는 대기 시한이 없으므로 스크립트에서 시한을 둔다. 시한은 정상 정지 최대 시간(약 11분)보다 길게, 예를 들어 15분으로 잡는다. -
시한을 넘기면 정지는 GritDB 안에서 계속된다.
--quick을 더 보내도 끼어들지 못한다. 그래서 사람이 QuickStart 7.4대로 살펴본다.timeout 900 ~/gritdb1/bin/gritdb-stop || echo "STOP TIMEOUT" -
감독 프로세스는 직접 받은
kill(SIGTERM)을 즉시 정지로 처리한다. 그래서 정상 정지는gritdb-stop으로만 한다.gritdb-stop도 정지 명령이 닿지 않으면 이 신호를 보낸다. -
재시작은
gritdb-stop을 먼저 실행한 뒤gritdb-start를 실행한다. 재시작 명령은 따로 없다(QuickStart 4.6).
4.3 크래시 때 동작 · 다시 기동
- GritDB 프로세스 하나가 비정상 종료하면 GritDB 전체가 정지한다. PostgreSQL 백엔드 하나의 비정상 종료(OS의 강제 종료 포함)도 같다. 자동 재기동은 없다. PostgreSQL의
restart_after_crash를 끈 것과 같다(5.3). - GritDB 엔진 프로세스나 GritDB 카탈로그 프로세스 하나만 따로 끝내도 전체가 즉시 정지한다.
- GritDB 프로세스에 HUP 신호(
kill -HUP)를 보내지 않는다. 보내면 프로세스가 끝난다.
비정상 종료 뒤 순서:
-
QuickStart 7.4의 기록과 수집을 끝낸다.
log/grit_admin_stdout.log는 다음 기동이 덮어쓴다.log/GRIT_SURFER_ASSERT.log의 크기를 본다. 0보다 크면 중단 기록이 있다. -
최대 1분 동안 QuickStart 4.5의 정지 확인을 실행해 GritDB 프로세스가 모두 사라졌는지 본다. 1분 뒤에도 남으면 QuickStart 7.4를 보고 지원 문의(0장)를 한다.
-
~/gritdb1/bin/gritdb-stop을 실행해 남은 PID 파일을 정리한다. 화면에GritAdmin PID file exists but process not running또는GritAdmin PID file not found경고가 보이면 정상이다. -
~/gritdb1/bin/gritdb-start를 실행한다. -
기동 경로를 확인한다.
grep DetectScenario ~/gritdb1/log/grit_admin_main.log | tail -1ABNORMAL_RESTART가 들어 있으면 정상이다. 비정상 종료 뒤 복구 경로로 기동했다는 뜻이다. -
8.5로 검증한다(반영 확인과 건수 대조).
다음 기동은 비정상 종료 경로로 복구를 거친다. 복구는 시한이 없다(4.1).
- PostgreSQL 복구(redo) 중에는
log/postgresql.log에redo starts at <LSN>→ 10초마다redo in progress, elapsed time: <초> s, current LSN: <LSN>→redo done at <LSN>줄이 차례로 남는다. 걸리는 시간은 마지막 checkpoint 뒤에 쌓인 WAL이 많을수록 길다. 튜닝 블록이checkpoint_timeout을 1h로,max_wal_size를 64GB로 정하므로(5.2) PostgreSQL 기본값으로 운영할 때보다 길 수 있다.current LSN이 나아가면 기다린다. 강제로 끝내면 다음 기동이 redo를 처음부터 다시 한다.grep -E 'redo (starts|in progress|done)' ~/gritdb1/log/postgresql.log | tail -3으로 확인한다. 간격은log_startup_progress_interval이 정한다(기본 10초).
- 복구 진행은
log/grit_recovery_worker_process.log에서 본다. 5초마다[WARN]등급의RecoveryWorker: recovery queue not drained after <ms> ms — Plug/Unify pipeline may be blocked while catalog writes are deferred줄이 남는다. 줄 끝의may be blocked …까지가 고정 문구다.<ms>가 늘어 가는 동안은 복구 중이므로 기동을 끊지 않는다(4.1). log/grit_admin_main.log에=== OpenSessionGate ===뒤PID file written줄이 남고, 이어서 화면에GritDB started successfully가 나오면 기동이 끝났다.
4.4 남은 프로세스 · 공유 메모리 정리
gritdb-stop이 스스로 정리하는 것:
- 남은 PID 파일을 지운다.
- 감독 프로세스가 내려간 뒤 남은 GritDB 엔진 프로세스와 PostgreSQL 프로세스를 실행 파일 이름으로 대조해 끝낸다.
- 이 설치본의 공유 메모리 잔여는 지우지 않고 개수만 알린다. 자세한 것은 QuickStart GDB-SHUTDOWN-001을 본다.
정지 뒤 남은 것을 본다.
- 프로세스는 QuickStart 4.5의 정지 확인으로 본다. 출력이 있으면 1분 기다린 뒤 다시 본다. 그래도 남으면
kill로 하나씩 끝내지 않는다. 이때는 QuickStart 7.4를 보고 지원 문의(0장)를 한다. - 공유 메모리는 감독 프로세스가 강제로 끝나면 남는다. 정지 뒤 잔여 경고가 나오면 프로세스가 0개인지 확인한 뒤 QuickStart GDB-SHUTDOWN-001대로 정리한다.
- 정상 정지나 즉시 정지 뒤에도 같은 경고가 되풀이되면 QuickStart 7.4를 보고 지원 문의(0장)를 한다.
프로세스 이름:
실행 파일(bin/) |
ps -o comm과 pgrep |
ps -ef(명령 줄) |
|---|---|---|
grit_admin |
GritAdmin |
GritDB for postgres: GritAdmin |
grit_surfer_process |
GritSurfer |
GritDB for postgres: GritSurfer |
grit_catalog_process |
GritCatalog |
GritDB for postgres: GritCatalog |
postgres |
postgres |
주 프로세스: <설치 경로>/bin/postgres -D …. 하위 프로세스: GritDB for postgres: <이름>(예: checkpointer, 세션은 <계정> <db> [local] idle) |
- 판별은
comm이름(pgrep -x)으로 한다. 설치 경로가 짧으면 명령 줄 이름이 실행 파일 경로로 보일 수 있다. - 설치본이 여럿이면 이름이 같으므로
/proc/<PID>/exe로 가른다(2.9).
4.5 상태 확인
상태 명령은 없다. 잠금, run/grit_admin.pid, 프로세스 이름, pg_isready를 함께 보고 판정한다.
| 상태 | PID 파일 | 잠금(run/gritdb.lock) |
|---|---|---|
| 실행 중 | 있다(4줄) | 잡혀 있다 |
| 기동 중 | 없다 | 잡혀 있다 |
| 정지 | 없다 | 풀려 있다 |
| 비정상 종료 뒤 | 있다(프로세스는 없다) | 풀려 있다. 4.3을 본다 |
flock -n ~/gritdb1/run/gritdb.lock true && echo "잠금 풀림 = 정지"
while IFS=: read -r k p || [ -n "$k" ]; do
printf '%-12s %-8s %s\n' "$k" "$p" "$(ps -p "$p" -o comm= || echo DEAD)"
done < ~/gritdb1/run/grit_admin.pid
~/gritdb1/bin/pg_isready -p 5432 -d postgres
- 정상(실행 중)이면 첫 줄은 출력이 없다. PID 4줄에
GritAdmin,GritSurfer,postgres,GritCatalog가 하나씩 나오고DEAD가 없다. 마지막 줄은accepting connections다. - 정지 상태면 첫 줄은
잠금 풀림 = 정지다. 둘째 줄은…/grit_admin.pid: No such file or directory(셸 오류)다. 마지막 줄은no response다. - 기동 중이면 첫 줄은 출력이 없다. 둘째 줄은 같은
No such file or directory다. 마지막 줄은rejecting connections다. 이때는 잠시 뒤 다시 본다. - 설치본이 여럿이면 프로세스 이름 대신
/proc/<PID>/exe로 구분한다(2.9).
4.6 서버 부팅 때 기동
제품에는 서비스 등록 파일이 없다. systemd를 쓰면 아래 예시를 바탕으로 /etc/systemd/system/gritdb.service를 만든다. 이 작업은 root로 한다.
[Unit]
Description=GritDB
After=network-online.target
Wants=network-online.target
RequiresMountsFor=<데이터 볼륨 실경로>
[Service]
Type=oneshot
RemainAfterExit=yes
User=gritdb
Environment=TMPDIR=<데이터 볼륨 안 디렉토리>
ExecStart=<설치 경로>/bin/gritdb-start
ExecStop=<설치 경로>/bin/gritdb-stop
TimeoutStartSec=infinity
TimeoutStopSec=20min
LimitNOFILE=65536
LimitCORE=<core 한도>
[Install]
WantedBy=multi-user.target
| 줄 | 이유 |
|---|---|
RequiresMountsFor |
데이터 볼륨(2.4)이 mount된 뒤 기동한다. <데이터 볼륨 실경로>는 readlink -f ~/gritdb1/datafiles의 값이다. 재배치하지 않았으면 이 줄을 뺀다 |
ExecStart와 ExecStop |
<설치 경로>에는 절대 경로를 쓴다(gritdb 계정에서 readlink -f ~/gritdb1의 값). 정지는 gritdb-stop으로 한다 |
Type=oneshot과 RemainAfterExit=yes |
gritdb-start는 기동이 끝나면 돌아온다. PID 파일 형식이 달라 PIDFile=을 쓰지 않는다 |
TimeoutStartSec과 TimeoutStopSec |
기동에는 시한이 없는 단계가 있다(4.1). 정지 시한은 정상 정지 최대 시간(약 11분)보다 길게 잡는다 |
LimitNOFILE과 LimitCORE |
/etc/security/limits.conf는 systemd 서비스에 적용되지 않는다(1.4) |
Environment=TMPDIR |
1.4의 ④를 본다. /tmp를 쓸 때는 이 줄을 뺀다 |
ExecReload 없음 |
HUP 신호를 받으면 GritDB 프로세스가 끝난다(4.3) |
Restart= 없음 |
비정상 종료 뒤에는 4.3 순서를 따른다. 자동 재시작을 걸지 않는다 |
- systemd로 띄운 셸 환경에는
PG로 시작하는 변수가 없다. 4.1의 기동하는 셸 조건에 맞는다. - 서비스로 띄워도
gritdb로 로그인했다 나가면 공유 메모리가 지워질 수 있다. 그래서 1.4 ⑤(RemoveIPC)를 먼저 한다. - PostgreSQL 쪽 서비스 예: 서버 시작
켜기와 기동(root):
systemctl daemon-reload
systemctl enable gritdb
systemctl start gritdb
- 손으로 띄운 GritDB가 떠 있으면 먼저
gritdb-stop으로 내린 뒤systemctl start를 실행한다. systemctl status가activating인 기동 중에는systemctl stop gritdb를 하지 않는다.active가 된 뒤 정지한다.systemctl status gritdb의 상태 줄이active (exited)인지 확인한다. 기동 명령이 끝난 뒤에도 GritDB는 돈다(Type=oneshot). 4.5로도 확인한다.- systemd로 띄웠으면 정지도
systemctl stop gritdb로 한다. 비정상 종료 뒤 4.3의 3번과 4번은 각각systemctl stop gritdb와systemctl start gritdb로 한다. - 작업 스케줄러나 CI 잡 실행기에서 기동하면 그 작업이 끝날 때 GritDB가 함께 종료될 수 있다. 그래서 서비스 관리자(systemd)로 기동한다.
4.7 계획 정지 (OS 패치 · 재부팅)
- 분석계면 멈춰 둘 수 있는 시간을 먼저 본다(아래).
- 작업 전 기준을 수집한다(7.7).
- 응용 프로그램을 멈추고 남은 세션을 끊은 뒤 정상 정지한다(4.2).
- 멈춘 것을 확인한다(4.5와 QuickStart 4.5의 정지 확인).
- OS 작업을 한다.
- glibc(QuickStart 2.4 점검표 4,
min_glibc이상)와 1.4의 파일 열기 한도,kernel.core_pattern, 시간 동기화, clocksource,RemoveIPC를 다시 확인한다. - 기동한다(4.1). 그 뒤 4.5로 확인한다. 부팅 때 기동(4.6)을 켜 두었으면 재부팅 뒤 4.5로 확인한다.
- 7.3의 “패치 때” 항목을 점검한다. 분석계면 따라잡는지 본다(7.5).
분석계를 멈춰 둘 수 있는 시간은 운영 DB에서 max_slot_wal_keep_size를 WAL 생성 속도로 나눈 값이다. 자세한 것은 6.4.1의 1번과 6.4.3을 본다. max_slot_wal_keep_size가 -1이면 그 대신 운영 DB 디스크 여유를 WAL 생성 속도로 나눈다. 이 시간을 넘으면 처음부터 다시 받는다(8.6).
WAL 생성 속도는 운영 DB에서 간격을 두고(예: 바쁜 시간대 1시간) 두 번 잰다.
SELECT pg_current_wal_lsn();
SELECT pg_size_pretty(pg_wal_lsn_diff('<나중 값>', '<처음 값>'));
- 결과는 그 간격 동안 쌓인 WAL 크기다. 함수 설명은
pg_current_wal_lsn과pg_wal_lsn_diff에 있다.
문제가 생기면
- QuickStart 7장의 GDB-BOOT 계열, GDB-SHUTDOWN 계열, TroubleShooting을 본다.
더 알아보기
- 감시 지표는 7장을, 로그는 9장을 본다.
- PostgreSQL 17 문서: 서버 정지, 서버 시작, 커널 자원(RemoveIPC), 서버 신호 함수