LabHub

PostgreSQL 장애 대응 · 계획과 지평선 · 실습

떠 있는 데이터베이스를 진단한다

LabHub 에서 이어서 보기

목표

세 가지 증상이 동시에 나 있는 데이터베이스를 받아, 각각의 원인을 숫자로
가려내고 마지막에 진단서 한 장으로 묶습니다. 고치는 것이 아니라 진단
이 실습의 과제입니다.

왜 중요한가

데이터베이스는 대개 죽지 않습니다. 떠 있는 채로 이상해지고, 그때 증상이
보이는 자리와 원인이 있는 자리는 거의 언제나 다릅니다. 막힌 세션이 가리키는
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

참고

단계 8개

  1. 사고를 재현하고 한 장으로 찍는다
  2. 사슬의 끝을 찾는다
  3. 대기가 무엇을 먹고 있나
  4. 안 바뀐 쿼리가 느려졌다
  5. 고칠 것은 쿼리가 아니었다
  6. 갱신했는데 표가 커졌다
  7. 청소를 막고 있는 것
  8. 진단서 한 장