Heroku Postgres-중단 된 쿼리 종료 (트랜잭션 유휴)


99

Crane Postgres 옵션과 함께 Heroku를 사용하고 있으며 로컬 시스템이 충돌했을 때 로컬 시스템에서 데이터베이스에 대한 쿼리를 실행하고있었습니다. 내가 달리면

select * from pg_stat_activity

항목 중 하나가

<IDLE> in transaction

current_query_text 열에 있습니다.

결과적으로 종료 된 쿼리에 의해 작성되고 있던 테이블을 삭제할 수 없습니다. pg_cancel_backend (N) 사용을 시도했지만 True를 반환하지만 아무 일도 일어나지 않는 것 같습니다.

테이블을 삭제할 수 있도록이 프로세스를 종료하려면 어떻게해야합니까?


1
아마도 질문은 "postgres 서버에 대한 루트 액세스 권한도없고 데이터베이스에 대한 수퍼 유저 액세스 권한도 없을 때 내 쿼리를 종료하는 방법"으로 다시 표현되어야합니다. 정말 좋은 질문 인 것 같고 ... 답을 모르겠습니다.
tobixen 2012-07-02

답변:


138

이것은 일반적인 Postgres 답변이며 heroku에만 국한되지 않습니다.


(이 질문에 대한 간단하고 어리석은 대답은 ... postgresql을 다시 시작하십시오. 바람직하지 않거나 옵션이 아니라고 가정하면 ...)

이 SQL을 실행하여 PID를 찾으십시오.

SELECT pid , query, * from pg_stat_activity
  WHERE state != 'idle' ORDER BY xact_start;

(쿼리는 postgres 버전에 따라 수정이 필요할 수 있습니다-결국 pg_stat_activity에서 *를 선택하십시오). 첫 번째 (왼쪽) 열에서 pid를 찾을 수 있으며 첫 번째 (맨 위) 행은 종료하려는 쿼리 일 가능성이 높습니다. 아래 pid가 1234라고 가정하겠습니다.

SQL을 통해 쿼리를 취소 할 수 있습니다 (즉, 쉘 액세스없이). 귀하의 쿼리이거나 수퍼 유저 액세스 권한이있는 경우 :

select pg_cancel_backend(1234);

1234 쿼리를 취소하라는 "친절한"요청이며, 운이 좋으면 잠시 후 사라질 것입니다. 결국 이것은 더 효율적입니다.

select pg_terminate_backend(1234);

셸 액세스와 루트 또는 postgres 권한이있는 경우 셸에서도 수행 할 수 있습니다. "취소"하려면 다음을 수행하십시오.

kill -INT 1234

"종료"하려면 간단히 :

kill 1234

하지 마라:

kill -9 1234

... 그것은 종종 전체 postgres 서버가 불타 오르는 결과를 낳을 것입니다. 그러면 postgres를 다시 시작할 수도 있습니다. Postgres는 매우 강력하므로 데이터가 손상되지는 않지만 어떤 경우에도 "kill -9"를 사용하지 않는 것이 좋습니다. :-)


오래 지속되는 "트랜잭션 유휴"는 종종 트랜잭션이 "커밋"또는 "롤백"으로 종료되지 않았 음을 의미합니다. 즉, 응용 프로그램이 버그가 있거나 트랜잭션 데이터베이스에서 작동하도록 제대로 설계되지 않았 음을 의미합니다. 장기적인 "트랜잭션 유휴"는 주요 성능 문제를 일으킬 수 있으므로 피해야합니다.


pg_cancel_backend를 아무 소용이 없었습니다. 셸 액세스 권한이없고 수퍼 유저가 아니므로 pg_terminate_backend를 사용하여 SIGKILL을 보낼 수 없습니다
alan

어떤 버전의 postgres를 사용하고 있습니까? (힌트 :) select version(). 사용할 때 오류 메시지가 표시 pg_cancel_backend됩니까?
tobixen 2012-07-02

pg_cancel_backend를 직접 사용하려고했기 때문에 "다른 서버 프로세스에 신호를 보내려면 수퍼 유저 여야합니다."라는 오류 메시지가 나타납니다. 즉, 서버에 대한 루트 액세스 또는 일부 postgres 수퍼 유저 (예 : postgres 사용자)를 통한 db 액세스가 필요함을 의미합니다. ) 자신의 쿼리를 죽일 수 있습니다. 그것은 조금 빨려 보인다 :-(
tobixen

1
프로세스가 pg_cancel_backend에 의해 취소되었지만 쿼리는 잠시 동안 pg_stat_activity에 계속 표시됩니다
alan

아마도 Heroku에만 국한된 것 같습니다. 내가 볼 수있는 한, 일반적인 postgres에서는 멈춘 프로세스를 죽이려면 수퍼 유저가되어야합니다 (8.4 페이지에서 "select pg_sleep (3600);"로 테스트하고 있습니다. "오류 : 신호하려면 수퍼 유저 여야합니다." 다른 서버 프로세스 "). 그러나 다시 "거래 유휴"는 완전히 동일하지 않습니다.
tobixen

36

이 시도:

select pg_terminate_backend(pid int)

이에 대한 자세한 내용은 여기에서 찾을 수 있습니다 . 이것은 시스템에 의한 프로세스를 죽이는 것보다이 문제의 '더 깨끗한'해결책이어야합니다.


당신의 대답에 PID를 얻는 방법을 추가하세요
mountainclimber

19

heroku-pg-extras애드온을 설치하고 다음 명령을 실행하여 PID를 가져올 수 있습니다.

heroku pg:locks --app <your-app>

그런 다음 다음을 수행하십시오.

heroku pg:kill <pid> --app <your-app> 

참고 :--force 옵션을 사용하여 해당 쿼리에 대한 전체 연결을 삭제하는 pg_terminate_backend를 실행할 수 있습니다.

경우 heroku pg:locks없는 목록 아무것도하지, 시도heroku pg:ps .

자세한 내용은 https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall을 확인하세요.


감사합니다. 그래도 트랜잭션 / PID를 종료 할 수 없습니다 ... 내 컴퓨터가 가져 오는 동안 하드웨어가 정지되어 PID를 종료 할 수 없습니다. :(
dimitarvp

-3

다음을 사용하여 단일 쿼리로이를 달성 할 수 있습니다.

SELECT pg_cancel_backend(pid), pg_terminate_backend(pid) FROM pg_stat_activity WHERE state != 'idle';

실행중인 모든 쿼리를 죽이면 postgres를 다시 시작할 수 있습니다. xact_start 및 제한 1에 의해 주문하고 동의 할 수 있습니다 ...하지만 다시 맹목적으로 죽이기 전에 목록을 보는 것을 선호합니다.
tobixen

이건 어때? SELECT pid, pg_cancel_backend(pid) FROM pg_stat_activity WHERE state != 'idle' AND (now() - query_start) > interval '5 minutes';
AFN 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.