PostgreSQL 장애 대응 · 계획과 지평선 · 실습
떠 있는 데이터베이스를 진단한다
목표
세 가지 증상이 동시에 나 있는 데이터베이스를 받아, 각각의 원인을 숫자로
가려내고 마지막에 진단서 한 장으로 묶습니다. 고치는 것이 아니라 진단이
이 실습의 과제입니다.
왜 중요한가
데이터베이스는 대개 죽지 않습니다. 떠 있는 채로 이상해지고, 그때 증상이
보이는 자리와 원인이 있는 자리는 거의 언제나 다릅니다. 막힌 세션이 가리키는
pid 는 자기도 막힌 피해자이고, 느려진 쿼리의 원인은 그 쿼리에 없고, 안 줄어드는
표의 원인은 그 표 안에 없습니다.
그래서 이 실습은 명령을 외우게 하지 않습니다. 증거를 뽑아 적어 내는 일만
시키고, 채점기는 그 숫자를 지금 살아 있는 데이터베이스에서 다시 뽑아 맞춰 봅니다.
어떻게 찾았는지는 자유이고, 진단이 맞아야 통과합니다.
환경
이 파드는 postgres 계정으로 돕니다. psql 만 치면 labdb 에 바로 붙습니다.
export PATH=/usr/lib/postgresql/16/bin:$PATHexport PGHOST=127.0.0.1 PGUSER=lab PGDATABASE=labdbpsql산출물은 전부 /root/inc/ 아래에 둡니다. mkdir -p /root/inc 를 먼저 하세요.
세션 여러 개가 필요합니다. 터미널이 하나뿐이므로 백그라운드로 띄웁니다.
아래 형태가 트랜잭션을 연 채 노는 세션을 만듭니다 — stdin 을 열어 두면
psql 이 다음 명령을 기다리며 idle in transaction 으로 남습니다.
( { printf 'begin;\nupdate orders set status = status where id = 1;\n'; sleep 3600; } \ | PGAPPNAME=nightly-batch psql -X -q ) >/dev/null 2>&1 </dev/null &세 리다이렉션을 모두 붙이세요. 하나라도 빠지면 셸이 그 세션을 기다립니다.
단계
1. 사고 재현 + 활동 스냅샷 → /root/inc/01-activity.txt
2. 잠금 사슬의 끝 → /root/inc/02-root.txt
3. 대기가 먹는 커넥션과 lock_timeout → /root/inc/03-waiting.txt
4. 무너진 실행 계획 → /root/inc/04-plan.txt
5. 통계를 고친 뒤 → /root/inc/05-stats.txt
6. 죽은 튜플과 vacuum 의 대답 → /root/inc/06-bloat.txt
7. 지평선을 쥔 세션 → /root/inc/07-horizon.txt
8. 진단서 → /root/inc/08-report.md
참고
- 사고를 낸 세션들은 끝까지 살려 두세요. 채점이 살아 있는 데이터베이스와
events표는 통계 자동 갱신만 꺼 두었습니다. 실무에서 이 상태는 대량 적재- 4단계의 집계 쿼리는 몇 초 걸립니다. 느린 것이 정상이고, 그 시간이 증거입니다.
대조하기 때문에, 중간에 끊으면 앞 단계가 다시 채점되지 않습니다.
실제 조치(누구를 끊을지)는 8단계의 진단서에 글로 적습니다.
직후 autoanalyze 가 돌기 전 몇 분 동안 저절로 생기는데, 실습 중에 그 몇 분이
지나가 버리면 4단계를 볼 수 없기 때문입니다. autovacuum 자체는 켜져 있습니다.
단계 8개
- 사고를 재현하고 한 장으로 찍는다
- 사슬의 끝을 찾는다
- 대기가 무엇을 먹고 있나
- 안 바뀐 쿼리가 느려졌다
- 고칠 것은 쿼리가 아니었다
- 갱신했는데 표가 커졌다
- 청소를 막고 있는 것
- 진단서 한 장