유휴 PostgreSQL 연결에 대한 시간 초과가 있습니까?


98
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                 
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle             

나는 그것들을 많이 본다. 우리는 연결 누출을 수정하려고합니다. 그러나 한편, 이러한 유휴 연결에 대한 제한 시간을 최대 5 분으로 설정하려고합니다.


DB에 어떻게 연결하고 있습니까? socketTimeout은 당신이 찾고있는 것일 수 있습니다.
Doon

이 레거시 Pylons 웹 앱이 있고 SQLAlchemy를 사용했지만 제대로 사용하지 않은 것 같습니다. 기억이 안나요. 우리는 누출을 고치려고 노력하고 있습니다. socketTimeout문서에서 DB에 대한 연결을 완전히 닫는 것처럼 보입니다. 각 유휴 상태를 닫으려고하는데 연결이 설정되는 즉시 카운터가 시작됩니다.
user1012451


@ user1012451 "각 유휴 상태 종료"라고 말하면 <IDLE> in transaction세션을 종료하고 세션을 실행 중이지만 <IDLE>상태로 두는 것을 의미 합니까? 즉, 트랜잭션을 종료하고 세션은 종료하지 않습니까? (비 공감 : 불분명 한 질문)
Craig Ringer

@CraigRinger 잠시 후 최대 클라이언트 연결에 도달합니다. 이를 해결하려면 webapp을 다시 시작해야합니다. 그러면 postgresql도 다시 시작해야합니다. 모든 연결이 사라집니다. idle영원히 볼 때 , 우리는 각 연결 / 세션에 시간 제한을 설정할 수 있는지 묻습니다 (정직하게 정확한 용어를 모릅니다, 죄송합니다). 트랜잭션이 잘못된해야 정상적인 웹 응용 프로그램의 뭔가를 5 분 걸린다면 ....
user1012451

답변:


120

풀링 된 연결을 닫지 못하기 때문에 응용 프로그램에서 연결 누수 가있는 것 같습니다 . 세션 에만 문제가있는 것이 아니라 전체적으로 너무 많은 연결이 있습니다.<idle> in transaction

연결을 끊는 것은 정답이 아니지만 괜찮은 임시 해결 방법입니다.

PostgreSQL 데이터베이스에서 다른 모든 연결을 부팅하기 위해 PostgreSQL을 다시 시작하는 대신 Postgres 데이터베이스에서 다른 모든 사용자를 분리하려면 어떻게합니까?를 참조하십시오. 그리고 활성 연결이있는 경우 PostgreSQL 데이터베이스를 삭제하는 방법은 무엇입니까? . 후자는 더 나은 쿼리를 보여줍니다.

시간 제한을 설정하려면 @Doon이 제안했듯이 PostgreSQL에서 유휴 연결을 자동으로 닫는 방법을 참조하십시오 . , PgBouncer를 사용하여 PostgreSQL을 프록시하고 유휴 연결을 관리하는 것이 좋습니다. 어쨌든 연결이 누출되는 버그가있는 응용 프로그램이있는 경우 이것은 매우 좋은 생각입니다. 나는 매우 강력 PgBouncer을 구성하는 것이 좋습니다.

TCP의 킵 얼라이브는 응용 프로그램이 여전히 연결되어 살아 있기 때문에, 그냥 안, 여기에 일을하지 않습니다.

PostgreSQL 9.2 이상에서는 새 state_change타임 스탬프 열과의 state필드 pg_stat_activity를 사용하여 유휴 연결 리퍼를 구현할 수 있습니다. 크론 작업을 다음과 같이 실행하십시오.

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < current_timestamp - INTERVAL '5' MINUTE;

이전 버전에서는 연결이 유휴 상태가 된시기를 추적하는 복잡한 체계를 구현해야합니다. 귀찮게하지 마십시오. pgbouncer를 사용하십시오.


4
좋지만 다른 PgAdmin 백엔드를 죽일 것입니다. 추가 조건 사용 application_name = ''
Andrew Selivanov

1
pgbouncer를 사용하는 경우 pg_terminate_backend를 실행할 수 있습니까?
Henley Chiu

@HenleyChiu 나는 특별히 확인하지 않았지만 왜 안되는지 모르겠습니다.
Craig Ringer

1
이 작업을 실행하면 내 WAL 보낸 프로세스를 죽인 것 같다
조셉 페르시

@CraigRinger psql 연결도 유휴 연결로 간주됩니다. 그리고 왜 애초에 유휴 연결을 닫아야합니까? 나는 pg와의 연결을 설정하는 장기 실행 코드가 일부 dml 작업을 수행 한 다음 대기열을 통해 메시지를 기다린 다음 더 많은 dml 작업을 수행합니다. 그럼에도 불구하고 postges와의 연결은 idle. 왜 닫아야하나요.
Viren 2016-04-15

73

PostgreSQL 9.6에는 idle_in_transaction_session_timeout설명을 수행해야하는 새로운 옵션 이 있습니다. 다음 SET과 같은 명령을 사용하여 설정할 수 있습니다 .

SET SESSION idle_in_transaction_session_timeout = '5min';

1
너무 간단한 것을 물어 보는 것은 짜증나지만 저는 일반적으로 데이터베이스에 익숙하지 않습니다.이 기능을 사용하는 방법에 대한 매우 기본적인 예를 들어 주시겠습니까?
sg

이전 버전의 PostgreSQL에서 이와 같은 것이 있습니까 ??
sdsc81

아니요, 이전 버전에는 다른 답변과 유사한 것이 필요합니다.
shosti

데이터베이스를 다시 시작할 때마다이 매개 변수를 설정해야합니까? 아니면 한 번 한 후에 잊을 수 있습니까? 감사합니다
fresko 2008 년

5
SET SESSION현재 세션에만 해당됩니다 (새 연결을 열면 기본값으로 돌아갑니다). eg ALTER DATABASE SET idle_in_transaction_session_timeout = '5min'를 사용하거나 구성 파일을 사용 하여 데이터베이스 수준에서 구성 매개 변수를 설정할 수도 있습니다 ( postgresql.org/docs/current/static/config-setting.html 참조 ).
shosti

22

PostgreSQL 9.1에서 다음 쿼리로 유휴 연결. 데이터베이스를 다시 시작해야하는 상황을 방지하는 데 도움이되었습니다. 이것은 주로 JDBC 연결이 열리고 제대로 닫히지 않은 경우 발생합니다.

SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';

1
pg_terminate_backend은 8.4 이후
앤드류 은행

8

postgresql 9.6 이상을 사용하는 경우 postgresql.conf에서 다음을 설정할 수 있습니다.

idle_in_transaction_session_timeout = 30000 (밀리 초)


0

외부 예약 작업없이 데이터베이스 세션 시간 초과를 활성화 할 수있는 가능한 해결 방법 은 내가 개발 한 확장 pg_timeout 을 사용하는 입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.