Heroku Postgres - завершение опроса (бездействует в транзакции)

Я использую Heroku с параметром Crane Postgres, и я запускал запрос в базе данных с моей локальной машины, когда моя локальная машина разбилась. Если я запустил

select * from pg_stat_activity

одна из записей имеет

<IDLE> in transaction

в столбце current_query_text.

В результате я не могу отбросить таблицу, на которую был написан запрос, который был прерван. Я попытался использовать pg_cancel_backend (N), и он возвращает True, но ничего не происходит.

Как я могу завершить этот процесс, чтобы я мог отказаться от таблицы?

Ответ 1

Это общий ответ, а не специфический для героку. В общем случае отмена запроса может потребовать, чтобы пользователь имел доступ суперпользователя, либо к серверу postgres, либо к базе данных postgres - кажется, что обычный пользователь не может убить свой собственный процесс запроса, не обращаясь за помощью к его администратору базы данных или sysadmin


Найдите PID, запустив этот sql:

SELECT procpid,* from pg_stat_activity 
WHERE current_query<>'<IDLE>' ORDER BY xact_start;

Вы найдете procpid в первом (левом) столбце, а первая (верхняя) строка, скорее всего, будет запросом, который вы хотите прекратить. Я предполагаю, что pid составляет 1234.

Вы можете отменить запрос через SQL (т.е. без доступа к оболочке, но вам, вероятно, нужен доступ суперзамена к базе данных):

select pg_cancel_backend(1234);

Это "мягкий" способ... запрос не исчезнет сразу. Если вы спешите, попробуйте следующее:

select pg_terminate_backend(1234);

Если у вас есть доступ к оболочке, вы также можете сделать это из оболочки:

kill -INT 1234

Если это не помогает, используйте:

kill 1234

НЕ НЕ:

kill -9 1234

..., что часто приводит к тому, что весь сервер postgres спускается в пламени, тогда вы можете перезапустить postgres. Postgres довольно устойчив, поэтому данные не будут повреждены, но я бы рекомендовал не использовать "kill -9" в любом случае; -)


"idle in transaction" означает, что транзакция не была прервана "фиксацией" или "откатом", что означает, что приложение работает неправильно или неправильно разработано для работы с транзакционными базами данных. Следует избегать длительного "простоя в транзакции", так как это также может вызвать серьезные проблемы с производительностью.

Ответ 2

Попробуйте следующее:

select pg_terminate_backend(pid int)

Подробнее об этом вы можете найти здесь. Это должно быть "более чистым" решением этой проблемы, чем процесс убийства системой.

Ответ 3

Вы можете установить надстройку 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