[PostgreSQL] 커넥션과 운영

[원본 링크]

다른 DB들도 마찬가지지만, PostgreSQL에서 가장 중요한 운영 리스크 중 하나가 커넥션의 관리다.

DB를 안정적으로 운영하기 위해서는 커넥션 개수를 적절한 선에서 유지하도록 신경쓸 필요가 있다.




커넥션과 세션, 트랜잭션

PostgreSQL에서 커넥션과 - 세션 - 트랜잭션은 사실상의 동의어라고 보면 된다.
DB Client는 하나의 커넥션마다 최대 1개의 트랜잭션을 생성해서 사용할 수 있으며, DB Server는 MVCC에 기반한 멀티세션 처리를 잘 제공한다.

PostgreSQL은 하나의 세션을 병렬로 실행하고 스케줄링하기 위해서 OS Process를 사용한다. 따라서 세션이 많아질수록 OS 프로세스 스케줄링으로 인한 성능 부하가 발생할 수 있다.

당연히 DB라고 해서 CPU 코어 개수 이상의 일을 동시에 할 수는 없으니, 코어 개수 이상의 세션이 열린다면 OS 프로세스 스케줄링에 의해서 점진적 처리가 된다
그리고 세션이 많아질수록 프로세스 또한 비례해 증가하므로, 세션이 많아지는 것은 그다지 좋지 않다.




CPU 스펙과 커넥션 부하

이런저런 이유들로 인해 커넥션의 개수는 DB에 유의미한 부하를 가한다.
그러면 커넥션의 개수를 몇개 정도로 유지하는 것이 좋을까?

사실 딱 정답이라고 할 수는 없지만, 보수적인 관점에서는 물리 코어당 2-4개 정도의 세션을 안정적인 상한선으로 잡곤 한다. 그래서 cpu 코어가 4개면 8-16개 정도를 유지하는 것이 권장된다. (active session 기준)

이런건 사실 좋진 않다.

쿼리로 세션 현황을 보려면 다음과 같은 쿼리를 날려보면 된다.

SELECT state, count(*)
FROM pg_stat_activity
GROUP BY 1;

이 active와 idle in tranascation 개수가 중요하다. 저게 적을수록 좋은 것이다.




커넥션 관리 팁

커넥션을 효과적으로 운영하는게 필요한 항목들을 몇가지 정리해본다.


커넥션 개수 제한

가장 중요한 것 중 하나는, 서버마다의 커넥션 개수 제한을 명확하게 지정하는 것이다.
대부분의 DB Client 라이브러리들을 커넥션을 필요한만큼 생성하는데, 그 MAX Connection 한도를 지정하는 옵션이 있다. 이걸 감당 가능한 선에서 조절하는 것이 중요하다.


서버리스 경계

24시간 고정된 사이즈에 개수로 떠있는 고전적인 서버 인프라라면 개수 제한만으로 충분하지만, 변칙적인 인프라 환경이라면 커넥션이 의도치 않게 튈 수 있다.
요청마다 독립된 프로세스를 띄우는 PHP 같은 경우에도 커넥션을 무제한으로 소모할 수 있다는 문제가 있고, 무제한으로 확장되며 커넥션을 독자적으로 소모하는 AWS Lambda 같은 인프라 리소스도 요주의 경계 대상이다.
이런걸 쓸때는 RDS Proxy나 pgBouncer 같은 중간 Pool 계층을 두거나, 메인 API 서버로 query 처리를 대행하는 식으로 우회하는 것을 권장한다.


트랜잭션 짧게 잡기

트랜잭션은 가급적이면 최소한도로, 짧게 잡는 것이 좋다. DB Client들은 기존 커넥션을 적절히 재사용하는 pool 로직들이 들어있으므로, 짧게 잡고 끝내면 커넥션을 재사용하면서 동시 세션을 적게 가져갈 수 있다.
트랜잭션을 열어놓고 길게 잡을수록 동시 세션-커넥션이 급증하게 될 확률이 높다.
pg 통계의 idle in tranascation 비율이 높다면, 트랜잭션을 길게 잡고 있다는 증거다.




참조
https://wiki.postgresql.org/wiki/Number_Of_Database_Connections