PostgreSQL의 16개 락 슬롯이 쿼리 성능을 망치는 이유
Sixteen Locks Ought to Be Enough for Anybody
PostgreSQL은 쿼리 실행 시 테이블의 모든 인덱스에 AccessShareLock을 걸어, 인덱스가 20개인 테이블은 단일 행 기본키 조회에도 22개의 락을 요구한다. 9.2부터 도입된 fast-path locking은 백엔드당 16개 슬롯만 제공해, 이를 초과하면 공유 락 테이블의 LWLock 경합으로 CPU가 폭증하고 처리량이 급감한다. PostgreSQL 18에서는 max_locks_per_transaction에 따라 슬롯이 동적으로 확장되어 이 문제가 해결된다.
여기서 분명히 해둘 점은, 이 실패 모드가 정확히 잘못된 테이블에 집중된다는 것이다. 인덱스가 너무 많은 테이블은 모든 쿼리가 건드리는 핵심 테이블이므로, 모든 쿼리가 그 비용을 치르고, 경합은 전체 쿼리율에 비례해 확대된다.