7. 모니터링 · 정기 점검

이 장을 마치면: 무엇을 얼마나 자주 보고, 어느 값에서 조치할지 정한다.

  • GritDB 1.1에는 메트릭 수집 엔드포인트가 없으므로 이 장의 명령과 SQL로 점검한다. 진단 쿼리 모음은 A.6에 있다.

7.1 감시 지표

지표 확인 방법 비고
프로세스 4.5 상태 확인 GritAdmin, GritSurfer, postgres, GritCatalog가 나오면 정상이다
접속 pg_isready accepting connections
디스크 사용률과 데이터 크기 df와 du datafiles/, log/, core 자리
WAL 크기와 복구용 복제 슬롯 보존량 pg_wal 크기와 pg_replication_slots gritsurfer_slot은 물리 슬롯이다. active = f면 정상이다. 삭제하지 않는다
긴 트랜잭션 pg_stat_activity의 xact_start 슬롯 전진을 막아 pg_wal이 커진다
cold file(GritDB 엔진이 분석 조회용으로 열 단위로 저장한 파일) 상태 get_gritsurfer_coldfiles()(6.5) STAGED가 쌓이면 unify checkpoint가 정체했다는 뜻이다. unify checkpoint는 GritDB 엔진이 영구 반영을 마친 WAL 위치다. PostgreSQL checkpoint와 다르다
unify checkpoint 나이 get_gritsurfer_unify_checkpoints()의 최신 행 오래 멈춰 있으면 이상이다
열린 파일 수 /proc/<PID>/fd 그 프로세스의 한도(/proc/<PID>/limits의 Max open files)와 비교한다. 명령은 7.3에 있다
공유 메모리 /dev/shm(인스턴스 ID 접미사)
GritDB 엔진 메모리 grit_unify_main.log의 통계 줄(process_rss). 명령은 표 아래에 있다 물리 메모리의 90%에 닿으면 GritDB가 멈추므로 80%를 경고로 둔다
한 트랜잭션 상한 접근 grep -h -e 'Expanded pool near max' -e 'cannot be supplied now' ~/gritdb1/log/grit_unify_*.log* 줄 앞 HybridMPMCPool[<이름>]의 이름이 RowVersion이면 6.8의 한 트랜잭션 상한이다. 다른 이름이어도 대응은 같다. 지원 문의 때는 그 줄을 그대로 낸다. near max는 상한의 80%를 넘었다는 뜻이다. 이때는 긴 트랜잭션, 큰 적재, unify checkpoint 나이를 본다. cannot be supplied now는 상한에 닿았다는 뜻이다. GritDB가 곧 멈출 수 있으므로 큰 트랜잭션을 멈추고 지원 문의를 한다(6.8)
로그 ERROR 수 QuickStart 5.2 회전된 파일(.1~.20)을 포함한다. postgresql.log를 logrotate로 회전하면 .1도 센다(9.4)
GRIT_SURFER_ASSERT.log 크기 ls -l 0보다 크면 중단이 있었다. 이때는 QuickStart 7.4를 본다
재기동 흔적 SELECT pg_postmaster_start_time(); 값이 바뀌었으면 재기동이 있었다. 자동 재기동은 없으므로 누가 왜 재기동했는지 확인한다

GritDB 엔진 메모리를 본다.

grep 'process_rss=' ~/gritdb1/log/grit_unify_main.log | tail -1
free -h
  • 엔진 메모리 %는 process_rss 값을 free -h의 Mem: 줄 total로 나눈 값이다. 판정 기준은 7.2에 있다. 경고 수준은 80%다.
  • process_rss의 GB는 1024 기준이므로 free -h의 Gi와 같은 단위다.
  • 통계 줄은 5초마다 남으므로 지금 파일(grit_unify_main.log)만 본다. 회전된 파일(.1~.20)을 함께 넣으면 오래된 값이 나올 수 있다.

GritDB는 PostgreSQL 안에서 작업자와 내부 접속을 늘 쓴다. pg_stat_activity에 보여도 끊지 않는다(4.2).

종류 pg_stat_activity에서 보이는 값 수
GritDB 작업자 backend_type: grit_admin_worker, gritstore_heartbeat, gritsurfer_recovery, GritSurferSlotManagerWorker 4
GritDB 내부 접속 application_name이 gritdb_catalog_로 시작한다 6(기본값). 수는 grit_surfer.catalog.read_threads + 2다(5.6)
SELECT CASE WHEN application_name LIKE 'gritdb\_catalog\_%' THEN 'internal'
            ELSE backend_type END AS kind,
       count(*)
FROM pg_stat_activity
WHERE backend_type IN ('grit_admin_worker', 'gritstore_heartbeat', 'gritsurfer_recovery',
                       'GritSurferSlotManagerWorker')
   OR application_name LIKE 'gritdb\_catalog\_%'
GROUP BY 1 ORDER BY 1;
  • 작업자 네 줄이 각각 1이고 internal 한 줄이 6(기본값)이면 정상이다.
  • watermark 작업자(GritSurfer Watermark Worker)도 늘 돈다. 데이터베이스에 접속하지 않아 pg_stat_activity에는 없다. pgrep -u gritdb -c -f 'GritSurfer Watermark Worker'를 실행해 1이 나오는지 확인한다.
  • max_connections를 쓰는 것은 내부 접속 6개뿐이다. 작업자는 max_connections를 쓰지 않는다(10.2).

7.2 임계치

지표 정상 경고 위험
프로세스(4.5) 4개 — 하나라도 없으면 4.3을 본다
접속(pg_isready) accepting connections — 기동 중이 아닌데 다른 값이 1분 넘게 이어지면 4.5와 QuickStart 7장을 본다
디스크 사용률(datafiles/). --pgdata로 설치했으면 pgdata 볼륨도 본다(7.3) 80% 미만 80% 이상이면 공간 확보를 계획한다 디스크가 가득 차면 QuickStart GDB-RUNTIME-002를 본다
GritDB 엔진 메모리(process_rss) 물리 메모리의 80% 미만 80% 이상 90%에 닿으면 GritDB가 멈춘다
한 트랜잭션 상한 접근(7.1) 줄이 없다 near max 줄 cannot be supplied now 줄
복구용 복제 슬롯 wal_status(A.6) reserved extended lost
cold file STAGED(A.6) 늘었다 줄었다 한다 며칠째 늘기만 하면 6.5를 본다 —
unify checkpoint 나이(A.6) 짧게 유지된다. 쓰기가 없어도 10초 안팎마다 나아간다(6.6.1) 계속 커진다 —
GRIT_SURFER_ASSERT.log 크기 0 — 0보다 크면 QuickStart 7.4를 본다. 문의가 끝나면 9.5대로 정지 상태에서 다른 이름으로 옮긴다. 다음 점검부터 0이 된다
ERROR 수(QuickStart 5.2) 전날과 비슷하다 갑자기 늘면 에러 문구로 QuickStart 7장을 검색한다 —
운영 DB의 분석계 subscription 슬롯 wal_status(7.5) reserved extended나 unreserved lost면 8.6을 본다
  • 칸이 비거나 숫자가 없는 지표는 unify checkpoint 나이, 복구용 복제 슬롯 보존량(7.3), log/ 하루 증가량(7.4)이다. 이런 지표는 운영을 시작하고 몇 주 동안 7.4 기록을 모아 그 서버의 값을 정한다.

7.3 정기 점검표

점검 명령 정상 범위 이상 시 주기 중요도
프로세스 4개 4.5 PID 4줄이 나오고 모두 살아 있다 4.3과 QuickStart GDB-RUNTIME-004 일 높음
접속 ~/gritdb1/bin/pg_isready -p 5432 -d postgres accepting connections 4.1과 QuickStart 7장 일 높음
디스크 사용률 df -h ~/gritdb1/datafiles/ ~/gritdb1/datafiles/pgdata/. --pgdata로 설치했으면 둘째 줄이 pg_wal 볼륨이다(2.4) 80% 미만(두 줄 모두) QuickStart GDB-RUNTIME-002 일 높음
데이터 크기 추이 du -sh ~/gritdb1/datafiles/* 급증이 없다(7.4) 7.4와 7.8 일 중간
ERROR 수 QuickStart 5.2의 5번 전날과 비슷하다 에러 문구로 QuickStart 7장과 TroubleShooting을 검색한다 일 중간
복구용 복제 슬롯 보존량 A.6 늘기만 하지 않는다. wal_status가 reserved다 긴 트랜잭션(A.6)과 TroubleShooting 일 높음
GRIT_SURFER_ASSERT.log 크기 ls -l ~/gritdb1/log/GRIT_SURFER_ASSERT.log 0 QuickStart 7.4 일 높음
GritDB 엔진 메모리와 한 트랜잭션 상한 접근 7.1 7.2의 정상 칸 6.8과 지원 문의(0장) 일 높음
분석계 subscription(분석계만) 7.5 7.5 정상 7.5 일 높음
로그 디렉토리 크기 du -sh ~/gritdb1/log 급증이 없다(7.4) 9.5 일 낮음
백업 결과 8.2의 확인 정한 주기의 백업이 있다 8.2 주 높음
등록 풀기 실패 WARNING 6.3의 grep 늘지 않는다(처음에는 0) 6.5와 지원 문의(0장) 주 중간
cold file 상태와 크기 A.6 STAGED가 늘기만 하지 않는다. 크기 추이는 7.4를 본다 6.5, 7.8, TroubleShooting 주 중간
unify checkpoint 나이 A.6 계속 나아간다(7.2) TroubleShooting과 지원 문의(0장) 주 높음
긴 트랜잭션과 남은 prepared transaction A.6 오래 열린 트랜잭션이 없다. pg_prepared_xacts가 0행이다 7.8 주 중간
정합 점검(표본 테이블) 7.10 일반 세션과 분석 세션의 결과가 같다(분석계면 운영 DB와도 같다) 6.7, 6.4.2, 8.6 주 높음
정비(트랜잭션 ID 나이와 죽은 행) 7.8 7.8 7.8 월 중간
정기 정리 7.6 7.6 — 월 낮음
열린 파일 수와 /dev/shm 아래 명령 그 프로세스의 한도보다 넉넉히 작다. /dev/shm에 여유가 있다 QuickStart GDB-RUNTIME-003 월 낮음
보안 점검표 11.10 모두 양호 11장 월 중간
업그레이드 전후 비교 3.4와 7.7의 기준 수집 바뀐 것이 계획한 변경(판 번호와 설정)뿐이다 3.7 패치 때 높음
OS 작업 뒤 확인 4.7 4.7의 확인 항목 1.4 패치 때 중간

열린 파일 수와 /dev/shm(서비스 계정):

for p in $(cut -d: -f2 ~/gritdb1/run/grit_admin.pid); do echo "$p $(ls /proc/$p/fd | wc -l) $(awk '/^Max open files/ {print $4, $5}' /proc/$p/limits)"; done
df -h /dev/shm
  • 출력 칸은 PID, 열린 수, 그 프로세스의 한도(soft와 hard)다. 셸의 ulimit이 아니라 이 값과 견준다. 부팅 때 서비스로 띄우면 limits.conf가 아니라 4.6의 LimitNOFILE이 한도다.

  • 한도가 65536 아래면 GritDB를 띄운 길을 본다. 부팅 기동은 4.6을, 손 기동은 1.4의 ①을 본다.

  • 중요도(높음, 중간, 낮음)는 그 점검을 거르면 생길 수 있는 영향의 크기다.

  • 지원을 요청할 때의 장애 등급은 구독 계약의 장애 등급(1 긴급~3 보통)을 따른다. 이 표의 중요도와 다르다.

7.4 점검 기록 · 추이

점검 결과를 매일 같은 표에 남긴다. QuickStart 5.3 표에 칸을 더한다.

날짜 디스크 % pgdata pg_wal cold_file cold_file 디렉토리 수 슬롯 보존량 log/ 엔진 메모리 % ERROR(GritDB / PG) ASSERT 크기 점검자
<날짜>

서비스 계정으로 값을 모은다. 슬롯 보존량은 A.6을, 엔진 메모리 %는 7.1을 본다. --pgdata로 설치했으면 디스크 % 칸에 두 볼륨을 함께 적는다.

df -h ~/gritdb1/datafiles/ ~/gritdb1/datafiles/pgdata/
du -sh ~/gritdb1/datafiles/* ~/gritdb1/log
du -sh ~/gritdb1/datafiles/pgdata/pg_wal
find ~/gritdb1/datafiles/cold_file -mindepth 1 -maxdepth 1 -type d | wc -l
grep 'process_rss=' ~/gritdb1/log/grit_unify_main.log | tail -1
free -h

추이로 판정한다.

  • 하루 증가량은 오늘 값에서 7일 전 값을 빼고 7로 나눈 값이다. 남은 날은 남은 공간을 하루 증가량으로 나눈 값이다.
  • 남은 날이 디스크를 늘리는 데 걸리는 시간보다 짧으면 볼륨을 늘린다. 경로는 그대로 둔다(1.5).
항목 이렇게 보면 이상이다 볼 곳
pgdata 적재량과 관계없이 계속 커진다 7.8(죽은 행)과 A.6(슬롯 보존량)
pg_wal max_wal_size(5.2)를 넘어 늘기만 한다 A.6(긴 트랜잭션과 unify checkpoint 나이)
cold_file 원본 데이터보다 훨씬 빨리 커진다 아래, 1.3, 7.8
cold_file 디렉토리 수 해제한 테이블이 없는데 계속 는다. 다시 기동한 뒤에도 줄지 않는다 7.6과 지원 문의(0장)
log/ 하루 증가량이 갑자기 커진다 9.3과 9.5
  • log/ 크기(du -sh ~/gritdb1/log)는 매일 적는다. 공용 로그 2개는 크기 회전이 거의 일어나지 않는다(9.3).
  • 갱신과 삭제가 많은 부하에서는 cold file이 원본 데이터보다 훨씬 커질 수 있으므로 cold_file 크기 추이로 디스크를 계획한다(1.3).

7.5 분석계 감시

분석계(6.4)는 운영 DB와 GritDB 두 쪽을 함께 본다. 운영 DB 쪽에서는 subscription 슬롯이 붙잡은 WAL과 슬롯 상태를 본다. GritDB 쪽에서는 subscription이 받고 있는지와 오류 수를 본다.

운영 DB에서(subscription 슬롯과 붙잡은 WAL):

SELECT slot_name, active, wal_status,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal,
       pg_size_pretty(safe_wal_size) AS safe_wal,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS behind
FROM pg_replication_slots
WHERE slot_name = '<sub>' OR slot_name LIKE 'pg\_<oid>\_sync\_%';
  • <oid>는 6.4.1의 8번에서 적은 subscription oid다. 대기 서버나 다른 CDC 도구의 슬롯을 섞지 않는다. 6.4.4의 2번과 같은 조건이다.

GritDB에서(subscription 상태와 오류 수):

SELECT subname, pid, latest_end_lsn, latest_end_time FROM pg_stat_subscription;
SELECT subname, apply_error_count, sync_error_count FROM pg_stat_subscription_stats;
  • 다음이 모두 맞으면 정상이다. 운영 DB 슬롯의 active가 t, wal_status가 reserved이고 retained_wal이 늘기만 하지 않는다. GritDB의 pid가 있고 latest_end_time이 계속 바뀌며 오류 수가 늘지 않는다.
  • wal_status가 extended면 슬롯이 운영 DB의 max_wal_size를 넘겨 WAL을 붙잡고 있다. 이때는 아래의 멈춘 신호를 본다. unreserved면 슬롯에 필요한 WAL이 다음 checkpoint에 지워진다. 이때는 바로 GritDB 쪽 원인을 푼다. 넘기면 lost가 된다(8.6).
  • safe_wal은 lost가 되기 전에 더 쌓일 수 있는 WAL 양이다. 운영 DB에 max_slot_wal_keep_size를 둔 때만 나오고, 그 값이 -1이면 빈 값이다. 멈춰 둘 수 있는 시간은 safe_wal을 WAL 생성 속도로 나눈 값이다(4.7).
  • behind는 GritDB가 아직 받았다고 알리지 않은 WAL 양이다. GritDB 엔진 반영은 6.6.1로 따로 본다.
  • SELECT subname, substream FROM pg_subscription;을 실행해 subscription 설정의 substream이 f인지 확인한다.
  • 뷰: pg_stat_subscription, pg_stat_subscription_stats

분석계가 멈추면(GritDB 정지나 적용 오류):

  • 운영 DB 슬롯이 WAL을 붙잡아 운영 DB 디스크가 찬다(6.4.3).
  • 상한은 운영 DB의 max_slot_wal_keep_size다. 자세한 것은 6.4.1의 1번과 6.4.3을 본다. 넘으면 운영 DB 슬롯이 무효가 되고 wal_status가 lost가 된다. 이때는 분석계를 처음부터 다시 받는다(8.6).
  • ⚠ GritDB 서버에는 max_slot_wal_keep_size를 설정하지 않는다(10.5).

subscription이 멈춘 신호:

신호 어디서
apply_error_count나 sync_error_count가 는다 GritDB pg_stat_subscription_stats
latest_end_time이 멈추거나 pid가 빈 값이다 GritDB pg_stat_subscription
logical replication이 든 ERROR가 되풀이된다 GritDB log/postgresql.log
retained_wal이 늘기만 하거나 active가 f다 운영 DB pg_replication_slots
wal_status가 extended나 unreserved다 운영 DB pg_replication_slots
grep -n -E 'ERROR: .*logical replication|logical replication (apply|tablesync) worker.* exited' ~/gritdb1/log/postgresql.log | tail -5
  • 오류 문구로 원인을 고른다.
    • has neither REPLICA IDENTITY index nor PRIMARY KEY는 GritDB 테이블에 기본 키가 없다는 뜻이다. 이때는 6.4.1의 6번을 본다.
    • is missing replicated column이나 does not exist는 운영 DB에서 열이나 이름을 바꿨다는 뜻이다. 이때는 6.4.2를 본다.
  • GritDB가 멈추고, 다시 띄울 때마다 분석계 적용 중에 또 멈추면 다시 띄우기를 되풀이하지 않는다. 운영 DB의 큰 트랜잭션이나 큰 테이블의 초기 복사가 한 트랜잭션 상한(6.8)을 넘었을 수 있다(6.4.3). 이때는 QuickStart 7.4로 자료를 모으고 지원 문의(0장)를 한다.

7.6 정기 정리 작업

아래는 GritDB가 스스로 지우지 않는 파일이다. 주기를 정해 지운다.

대상 자리 지우는 때와 방법 절
회전된 GritDB 로그 log/*.log.<N> 보존 기간이 지난 것. 실행 중에 지워도 된다 9.5
PostgreSQL 로그 log/postgresql.log 회전을 설정한다(설치 기본에서는 회전하지 않는다) 9.4
core 파일 kernel.core_pattern 자리 지원 문의가 끝난 뒤 9.6
재초기화가 남긴 옛 데이터 *.old-<일시> 필요 없어진 뒤 --purge-old 3.3
비정상 종료 뒤 임시 파일 datafiles/buffer_spill/과 기동한 셸의 TMPDIR(없으면 /tmp)의 __tkidx_spill_*.tmp GritDB를 정지한 상태에서만 1.4
분석 질의 원문 파일 datafiles/query_text_archive.jsonl 실행 중에 옮길 수 있다. 보관 규정에 따른다 9.5와 9.7

비정상 종료 뒤 남은 임시 파일을 찾는다. GritDB를 정지한 상태에서 서비스 계정으로 실행한다.

ls -la ~/gritdb1/datafiles/buffer_spill/
ls -la "${TMPDIR:-/tmp}"/__tkidx_spill_*.tmp
  • 정상 정지 뒤에 둘 다 비어 있으면 정상이다. No such file or directory가 나와도 비어 있는 것으로 본다.
  • 해제하거나 DROP한 테이블의 cold file 디렉토리는 GritDB가 그 cold file을 지운 뒤 지운다. 비정상 종료로 남은 빈 디렉토리는 다음 기동 때 정리한다. 그래서 손으로 지우지 않는다. 새로 등록한 테이블의 디렉토리는 첫 행이 반영될 때 생긴다(6.3).
  • 긴 분석 세션 조회는 cold file의 디스크 회수를 늦춘다. 조회가 끝나면 회수된다(7.8).

7.7 운영 시작 전 점검

# 확인 볼 곳 정상
1 서버 사양과 메모리 하한 1.3 계획한 사양이다
2 OS 설정(파일 열기 한도, core, 시간 동기화, TMPDIR) 1.4 각 항목의 확인이 끝났다
3 인증과 원격 접속 11.3과 11.4 trust 줄이 없다. 정한 주소만 열려 있다
4 설정 5장 운영 값을 ALTER SYSTEM으로 넣었다. timedatectl의 Time zone과 SHOW timezone;이 같다(5.3)
5 백업 계획과 첫 복구 시험 8.2, 8.4, 8.5 복구한 결과가 8.5 대조를 통과했다
6 감시와 정기 점검 7.3과 7.9 담당, 주기, 알림 대상이 정해졌다
7 로그 회전과 보존 9.4와 9.5 postgresql.log 회전이 설정되었다
8 서버 부팅 때 기동 4.6 재부팅 뒤 4.5가 정상이다
9 보안 점검표 11.10 모두 양호
10 지원 문의 경로 0장과 QuickStart 7.4 문의처, 계약 정보, 수집 절차를 운영 기록에 적었다
11 기준 수집 아래 수집물이 있다

운영을 시작할 때 기준 수집을 한 번 남긴다. 계획 작업(3.4 업그레이드나 4.7 계획 정지) 전후에도 같은 수집물을 남겨 비교한다.

B=~/gritdb_baseline_$(date +%Y%m%d_%H%M%S)
mkdir -p "$B"
{ date; uname -a; free -g; df -h; ulimit -a; } > "$B/system.txt" 2>&1
for p in $(cut -d: -f2 ~/gritdb1/run/grit_admin.pid); do echo "== $p"; cat /proc/$p/limits; done >> "$B/system.txt" 2>&1
cp ~/gritdb1/share/gritdb/manifest.json "$B/"
cp ~/gritdb1/datafiles/pgdata/postgresql.conf ~/gritdb1/datafiles/pgdata/postgresql.auto.conf ~/gritdb1/datafiles/pgdata/pg_hba.conf "$B/"
cp -r ~/gritdb1/config "$B/"
~/gritdb1/bin/psql -p 5432 -d postgres -c "SELECT name, setting, source FROM pg_settings WHERE source NOT IN ('default', 'override') ORDER BY 1" > "$B/settings.txt"
~/gritdb1/bin/psql -p 5432 -d <db> -c "SELECT schema_name, table_name, register_ts FROM get_gritsurfer_tables() ORDER BY 1, 2" > "$B/tables_<db>.txt"
tail -n 200 ~/gritdb1/log/grit_admin_main.log > "$B/grit_admin_main_tail.txt"
ls -l "$B"
  • <db>에는 등록 테이블이 있는 데이터베이스를 하나씩 넣어 되풀이한다.
  • ls -l "$B"를 실행해 파일이 모두 있고 크기가 0이 아닌지 확인한다.
  • 비교하려면 작업 뒤 같은 명령으로 모은 뒤 diff -r <작업 전 수집> <작업 후 수집>을 실행한다. 바뀐 줄이 계획한 변경(판 번호와 설정)뿐인지 확인한다.
  • 수집물에는 서버 설정이 들어 있으므로 설치 경로와 같은 권한으로 둔다(11.7).

7.8 정비 (VACUUM · 통계 · 트랜잭션 ID)

  • autovacuum을 끄지 않는다. SHOW autovacuum;을 실행해 on이 나오는지 확인한다.

트랜잭션 ID 나이(데이터베이스마다):

SELECT datname, age(datfrozenxid) AS xid_age FROM pg_database ORDER BY 2 DESC;

죽은 행(팽창, 등록 테이블이 있는 데이터베이스마다):

SELECT schemaname, relname, n_live_tup, n_dead_tup, last_autovacuum
FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 10;
  • n_dead_tup이 n_live_tup에 비해 작고 last_autovacuum이 최근이면 정상이다.

VACUUM을 막는 것:

원인 찾는 법
긴 트랜잭션과 idle in transaction A.6의 긴 트랜잭션
남은 prepared transaction(2단계 commit) SELECT gid, prepared, owner, database FROM pg_prepared_xacts;의 결과가 0행이면 정상이다. 뷰 설명은 pg_prepared_xacts에 있다
분석계 초기 복사(운영 DB 쪽) 6.4.3을 본다. 큰 테이블은 한가한 때 붙인다
해도 되는 정비 하지 않는 정비
VACUUM, ANALYZE, REINDEX, 인덱스 만들기와 지우기 VACUUM FULL, CLUSTER(등록 테이블, 6.7), GritDB 내부 테이블(postgres 데이터베이스의 gritdb 스키마)에 손대기(10.5)
  • cold file의 compaction과 정리는 GritDB가 스스로 한다. 바꾸는 설정은 없다. compaction은 작은 cold file을 큰 cold file로 합치는 GritDB 엔진의 일이다. 로그는 grit_unify_cold_store_compactor_gc_processor.log다(9.1).
    • 긴 분석 조회가 있거나 unify checkpoint가 정체하면 늦어진다. 조회가 보는 파일은 그 조회가 끝난 뒤 지운다.
    • get_gritsurfer_coldfiles()의 INACTIVE와 STAGED 크기 추이로 확인한다(A.6, 7.4).

7.9 감시 도구에 붙이기

메트릭 수집 엔드포인트가 없으므로 점검 스크립트가 값과 종료 코드를 내고, 사내 감시 도구가 그 스크립트를 주기적으로 실행한다.

아래는 서비스 계정으로 실행하는 예다. 종료 코드 0은 정상, 2는 이상을 뜻한다.

#!/bin/bash
G=~/gritdb1
rc=0
if ! "$G/bin/pg_isready" -q -p 5432 -d postgres; then
  echo "CRITICAL connect"; rc=2
fi
n=$(ps -o comm= -p "$(cut -d: -f2 "$G/run/grit_admin.pid" 2>/dev/null | paste -sd,)" 2>/dev/null | wc -l)
if [ "$n" -ne 4 ]; then
  echo "CRITICAL processes=$n"; rc=2
fi
if [ -s "$G/log/GRIT_SURFER_ASSERT.log" ]; then
  echo "CRITICAL assert_log"; rc=2
fi
echo "slot_retained_bytes=$("$G/bin/psql" -p 5432 -d postgres -Atc "SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) FROM pg_replication_slots WHERE slot_name = 'gritsurfer_slot'")"
echo "postmaster_start=$("$G/bin/psql" -p 5432 -d postgres -Atc "SELECT pg_postmaster_start_time()")"
exit "$rc"
  • 그 밖의 값을 보려면 A.6 진단 쿼리를 같은 꼴(psql -Atc)로 더한다.
  • 종료 코드의 뜻은 감시 도구의 관례에 맞게 바꾼다.
  • 정상일 때 스크립트를 실행한 뒤 echo $?를 실행해 0이 나오는지 확인한다.
  • CRITICAL assert_log가 이어지면 이미 문의한 기록인지 본다. 이미 문의한 기록이면 9.5대로 옮긴 뒤 다시 실행한다. 그러면 그 줄이 사라진다.

로그 감시:

볼 것 이상
GRIT_SURFER_ASSERT.log 크기 0보다 크면 QuickStart 7.4를 본다
ERROR 줄 수(QuickStart 5.2의 5번) 갑자기 는다
프로세스 4개(4.5) 하나라도 없으면 4.3을 본다
재기동 흔적(SELECT pg_postmaster_start_time();) 값이 바뀌었다. 자동 재기동은 없으므로 누가 왜 다시 띄웠는지 확인한다(4.3)

7.10 정합 점검

일반 세션과 분석 세션의 결과가 같은지 정해진 주기로 확인한다(주 1회, 7.3).

  1. 표본 테이블을 정한다. 자주 조회하는 테이블을 고른다. 갱신과 삭제가 많은 테이블도 고른다. 숫자 열은 정수나 numeric(p, s) 열을 고른다. real이나 double precision 합계는 끝자리가 다를 수 있다(10.3).
  2. 그 테이블 쓰기를 멈추거나 쓰기가 없는 때를 고른다.
  3. 분석계면 운영 DB 쪽 따라잡기를 확인한다(6.4.1의 9번 차례 1~2).
  4. 반영을 확인한다(6.6.1).
  5. 같은 쿼리로 잰다.

일반 세션(분석계면 운영 DB에서도):

SELECT count(*), sum(<숫자 열>) FROM <s>.<t>;

분석 세션(6.6, GritDB 엔진 강제, 6.6.1):

/*+ engine=burst, fallback=false */ SELECT count(*), sum(<숫자 열>) FROM <s>.<t>;
  1. 판정한다.
    • 같으면 7.4 기록에 적는다.
    • 다르면 그 테이블에 6.7의 작업(TRUNCATE, 열 변경 등)이 있었는지 본다. 한 데이터베이스 구성이면 6.7의 “테이블 다시 만들기”를 한다. 분석계면 6.4.2대로 그 테이블을 다시 받는다. 여러 테이블이 다르면 8.6을 본다.
    • 원인을 모르면 QuickStart 7.4로 자료를 모으고 지원 문의(0장)를 한다.
  • 5번의 값이 모두 같은지 확인한다(일반 세션, 분석 세션, 분석계면 운영 DB까지).

문제가 생기면

  • 점검표 “이상 시” 칸의 TroubleShooting 항목을 본다. TroubleShooting을 받지 못했으면 지원 문의(0장)를 한다.

  • 응답이 없거나 프로세스가 줄었으면 재기동하기 전에 지금 상태를 남긴다. 아래 명령은 QuickStart 7.4의 4번에서 tar 줄 전에 같은 셸(cd ~, $S)에서 실행한다.

    ps -u gritdb -o pid,stat,wchan:32,etime,args > "$S/process_state.txt" 2>&1
    timeout 15 ~/gritdb1/bin/psql -p 5432 -d postgres -X -c "SET statement_timeout = '10s'" -c "SELECT now(), pid, backend_type, usename, datname, state, wait_event_type, wait_event, xact_start, query_start, pg_blocking_pids(pid) FROM pg_stat_activity ORDER BY backend_start" > "$S/activity.txt" 2>&1
    timeout 15 ~/gritdb1/bin/psql -p 5432 -d postgres -X -c "SET statement_timeout = '10s'" -c "SELECT * FROM pg_replication_slots" -c "SELECT gid, prepared, owner, database FROM pg_prepared_xacts" > "$S/slots.txt" 2>&1
    timeout 15 ~/gritdb1/bin/psql -p 5432 -d postgres -X -c "SET statement_timeout = '10s'" -c "SELECT max(ckpt_lsn), now() - max(created_at) FROM get_gritsurfer_unify_checkpoints()" > "$S/unify_checkpoint.txt" 2>&1
    timeout 15 ~/gritdb1/bin/psql -p 5432 -d <db> -X -c "SET statement_timeout = '10s'" -c "SELECT seq, pid, query_start_time, query_hash, status, session_start_time FROM get_gritsurfer_active_queries()" > "$S/active_<db>.txt" 2>&1
    
    • 마지막 줄은 등록 테이블이 있는 데이터베이스마다 실행한다. 질의 원문 열 query와 query_text는 남기지 않는다(9.7).
    • 줄마다 15초 안에 끝난다(timeout). 붙지 못하거나 끝나지 않으면 파일에 오류가 남거나 파일이 비어 있다. 이때는 그대로 보내고 QuickStart 7.4의 3번 기록에 적는다.
    • 쿼리 뜻은 A.6을 본다. 함수 설명은 pg_blocking_pids에 있다. 보낼 묶음은 9.7을 본다.

더 알아보기