SMALL

PostgreSQL 11

PgBouncer transaction vs session 모드, 뭘 쓸까

Postgres 앞에 PgBouncer를 두는 건 거의 관습처럼 되어 있다. 그런데 막상 처음 도입할 때 보면 pool_mode 선택지가 세 개 있고, 그중 실제로 쓰는 건 거의 둘 — transaction과 session이다. 둘 다 써본 입장에서 정리해본다. 어느 쪽이 정답이라기보다, 트레이드오프가 꽤 명확하다.참고로 PgBouncer 1.21 이후 transaction 모드에서도 prepared statements가 지원되기 시작했다. 이게 의외로 선택 기준을 흔든다. 예전에는 ORM/드라이버 호환성 때문에 어쩔 수 없이 session 모드를 골랐던 케이스들이 다시 transaction으로 돌아갈 만한 여지가 생겼다.session 모드 — 가장 안전하지만 풀링 효과가 약하다pool_mode = se..

IT/DB 운영 00:44:07

autovacuum이 돌고 있는 줄 알았다

autovacuum이 돌고 있는 줄 알았다지난주에 PostgreSQL 디스크가 갑자기 부풀어오르는 사건이 있었다. 정확히는 이미 며칠 전부터 부풀고 있었는데, 우리가 늦게 알아챈 거다.처음에는 단순히 "데이터가 많아져서 그렇겠지" 생각했다. 그런데 dead tuple 비율을 찍어보니 40%를 넘기고 있었다. 어떤 테이블은 60%. 라이브 row보다 죽은 row가 더 많은 상태였다. autovacuum 로그를 뒤져보니 마지막 vacuum이 4일 전에 멈춰 있었다. 그리고 그 사이에 누가 무엇을 했는지 추적이 시작됐다.pg_stat_activity가 말해준 것pg_stat_activity 뷰를 열어보니 한 세션이 4일째 살아 있었다. state는 idle in transaction. xact_start는 월..

IT/DB 운영 2026.06.22

pgbouncer transaction mode에서 prepared statement 깨진 새벽 사건

지난주 새벽에 또 깼다. 4시쯤 핸드폰이 미친 듯이 울리는데, 화면을 보니 prepared statement "S_42" does not exist 에러가 분당 수천 건씩 쌓이고 있었다. 결제 API 쪽이었는데, 그날따라 더 짜증났던 건 — 두 시간 전에 내가 직접 머지한 PR 때문이라는 게 거의 확실했기 때문이다.결론부터 말하면 pgbouncer transaction pooling 모드 + 새 JDBC 드라이버 조합이 문제였다. 근데 거기까지 가는 과정이 정말 길었다.새벽 4시, 일단 롤백부터운영 룰은 단순하다. 새벽에 깨면 일단 의심되는 배포부터 롤백. 두 시간 전 머지한 PR이 두 개 있었다 — 하나는 pgbouncer 버전 업(1.18 → 1.23), 다른 하나는 백엔드 서비스의 PostgreSQ..

IT/DB 운영 2026.06.17

RDS PostgreSQL 16→17 업그레이드 새벽 작업기 — replication slot에 또 당했다

RDS PostgreSQL 16→17 업그레이드 새벽 작업기 — replication slot에 또 당했다지난주 토요일 새벽 2시. RDS PostgreSQL 16에서 17로 메이저 업그레이드를 돌렸다. 작업 자체는 한 시간 안에 끝날 줄 알았는데, 결국 새벽 6시까지 책상에 앉아있었다. 또 replication slot이었다.분명히 사전 점검 체크리스트에 "logical replication slot 확인" 항목을 넣어뒀다. 그런데도 당했다. 어떻게 당했는지, 그리고 이번에 알게 된 게 뭔지 적어둔다. 다음에 또 같은 데서 미끄러지지 않으려고.사전 점검은 했는데작업 전 점검은 평소대로 돌렸다.SELECT slot_name, plugin, slot_type, database, active, restart..

IT/DB 운영 2026.06.10

PgBouncer transaction mode에 prepared statement 켰다가 새벽에 깬 이야기

지난주 일요일 새벽 2시쯤 알림이 왔다. 결제 API 쪽에서 prepared statement "S_3" does not exist 에러가 분당 수백 건씩 찍히고 있었다. 그 전날 PgBouncer를 1.25.1로 올린 게 화근이었다. 안 그래도 PG16.11에 PgBouncer 1.25.1 조합에서 prepared statement 관련 버그 리포트가 올라온 게 있었는데, 우리도 그 케이스에 정확히 걸려든 거였다.이번 글은 그날 새벽 내가 뭘 보고 뭘 했고, 최종적으로 어떻게 마무리됐는지에 대한 기록이다. 깔끔한 해결책 같은 건 아직 없다. 워크어라운드로 일단 막아둔 상태.배경: 왜 transaction mode + prepared statement를 켰나작년에 우리 팀은 PgBouncer를 1.21로..

IT/DB 운영 2026.05.25

Aurora PostgreSQL 14 → 16 Blue/Green 업그레이드에서 삽질한 새벽 이야기

지난주 화요일 새벽 2시, 메이저 버전 업그레이드를 한다고 멘션이 와있었고 나는 콘솔 앞에 있었다. 사전 리허설은 두 번 했다. 스위치오버 30초, 길어야 1분. 그런데 실제 작업은 7분 걸렸다. 7분이라는 숫자 자체보다, 그 7분 동안 회사 메인 서비스의 결제 API가 절반쯤 죽어있었다는 게 문제였다.이 글은 그날 무슨 일이 있었는지, 그리고 다음에 같은 작업을 또 한다면 뭘 다르게 할지에 대한 기록이다. AWS 공식 문서나 베스트 프랙티스 글들이 말하지 않는 것들이 좀 있더라.시작은 평범했다대상은 Aurora PostgreSQL 14.10 클러스터다. 14가 2026년 11월에 standard support가 끝난다는 공지가 작년 말에 나왔고, 우리는 6월 안에 16으로 올리기로 했다. 17이 아니라..

IT/DB 운영 2026.05.20

PgBouncer transaction pooling, prepared statement 함정에서 빠져나온 이야기

지난주 화요일 오후, 모니터링 알람이 울렸다. PgBouncer 앞단의 connection 사용량이 평소 대비 3배 가까이 튀어 있었고, 어플리케이션 쪽 P99 레이턴시는 슬슬 200ms를 넘기고 있었다. 트래픽은 평소 수준. 이상한 점은 RDS Postgres의 active connection 수가 거의 변동이 없다는 거였다. 즉, 클라이언트 → PgBouncer 사이에서 뭔가 막혀 있다는 뜻이다.이번 글은 그날 밤 새벽 2시까지 잡고 있던 이 문제를 어떻게 추적했는지, 그리고 결국 prepared statement와 transaction pooling이 충돌하던 지점을 어떻게 풀어냈는지에 대한 기록이다. 결론부터 말하면, 우리가 두 달 전에 한 PgBouncer 버전 업그레이드가 진짜 원인이었다.처음..

IT/DB 운영 2026.05.14

pg_stat_io로 새벽 3시에 vacuum I/O 폭탄 잡은 이야기

지난주 화요일 새벽 3시, 슬랙 알림이 미친 듯이 울렸다. 결제 DB의 P99 레이턴시가 평소 12ms에서 280ms로 튀어 올랐다. 폰을 더듬어 잡고 일어나면서 머리가 멍했다. 트래픽은 한산한 시간대인데 왜?처음엔 단순한 락 경합인 줄 알았다. pg_stat_activity 봤는데 long-running 쿼리도 없고, pg_locks도 깨끗했다. 근데 디스크 IOPS는 평소 대비 4배. 뭔가 백그라운드에서 디스크를 갈아먹고 있는 게 분명한데 보이질 않았다. 멘탈이 살짝 나갔다.pg_stat_io를 켰다작년에 PG16으로 올리면서 pg_stat_io 뷰를 알게 됐었는데, 평상시엔 잘 안 보던 거였다. 이번 같은 상황에서 진가를 발휘하는 뷰다. context 컬럼에 bulkread, bulkwrite, v..

IT/DB 운영 2026.05.01

PgBouncer transaction 모드에서 prepared statement 제대로 쓰는 법

왜 굳이 켜야 하나PgBouncer 1.21에서 transaction pooling 모드에서도 prepared statement를 쓸 수 있게 된 게 벌써 2년 가까이 됐다. 우리 팀도 작년 가을에 1.22로 올리고 max_prepared_statements를 켰는데, 그동안 마주친 함정 몇 개가 있어서 정리해둔다. 비슷한 마이그레이션을 앞두고 있는 분들에게 도움이 됐으면 한다.이 글은 "PgBouncer는 뭔가요"부터 시작하지 않는다. 이미 transaction 모드로 PgBouncer를 운영 중이고, 애플리케이션이 prepared statement를 쓰고 있거나 쓰고 싶은 상황을 가정한다.JDBC, asyncpg, pgx, psycopg3 같은 모던 드라이버는 기본적으로 Parse/Bind/Execu..

IT/DB 운영 2026.04.29
BIG