Ok

En poursuivant votre navigation sur ce site, vous acceptez l'utilisation de cookies. Ces derniers assurent le bon fonctionnement de nos services. En savoir plus.

[Postgres] Identifier les attentes

This query allows you to identify the wait events on which query .

How to Find and Stop Running Queries on PostgreSQL

Find a query with his pid.

This query allows you to identify the wait events on which query .

select pid, query_start, age(clock_timestamp(), query_start) as age, state, wait_event_type, wait_event, LEFT(query, 40)
from pg_stat_activity where state not like '%idle%' and datname = 'mydatabase'
order by query_start asc limit 50;

How to Find and Stop Running Queries on PostgreSQL


Stopping Queries via SQL in Two Steps

Here’s the basic process to find and stop a query. Note you’ll need to connect as a user with adequate permissions to do so, such as an admin account.

1. Find the pid

PostgreSQL creates one process per connection, and it identifies each process with its operating system process ID, or pid. In order to cancel a query, you need to know the pid for the connection it’s running on.

One way to find this out is with the pg_stat_activity view, which provides information about the live queries. For example, try this query:

SELECT pid, state, backend_start, substr(query, 0, 100) q
FROM pg_stat_activity
WHERE backend_type = 'client backend'
ORDER BY backend_start;

The substr call limits the displayed SQL to 100 characters, to avoid long queries taking up a lot of screen space. The backend_type filter avoids showing background server processes, such as the autovacuum launcher. Sorting by backend_start shows the longest running connections first, which often shows problematic long-running transactions.

2. Terminate, or Cancel, the Process

PostgreSQL has two query-stopping functions, with differences discussed below.

The “harsh” one is pg_terminate_backend, which you can use like:

SELECT pg_terminate_backend(pid);

I default to using this one, reasoning explained below.

The “kinder” function is pg_cancel_backend, which you can use like:

SELECT pg_cancel_backend(pid);

When using either, replace pid with the pid you found in step 1. For example, to terminate the long-running query from above:

SELECT pg_terminate_backend(77);

And boom, it’s gone.

There are two differences that make pg_terminate_backend “harsher”.

First, pg_terminate_backend completely stops the process, causing the connection to close. This rolls back any open transaction on the connection, freeing all locks it holds.

In contrast, pg_cancel_backend interrupts only the running query, leaving the connection open. The current transaction or savepoint is aborted. Thus, if the connection is using savepoints, it can still keep the surrounding transaction open, with pending data changes and locks.

Second, pg_terminate_backend applies immediately*, whilst pg_cancel_backend can be deferred at certain points in the backend process lifecycle. So sometimes, you might run pg_cancel_backend and see nothing happen for a while. Specifically, this can occur when the process is reading input from the client, such as an incoming query. The backend process defers handling the cancellation until all the input has been read, since otherwise the connection could not be left open and functional.

 

Queries Blocking a Particular Process

If you’re executing an ALTER TABLE and find it blocked, waiting for a table lock, you may want to terminate the connections holding locks on that table. This will allow the ALTER TABLE to proceed.

For example, I recently worked on an application with a few long-running transactions that blocked a database migration. These long-running queries were safe to terminate as the responsible application process would re-run later and fill in any gaps.

You can find the blocked pid of ALTER TABLE with a query against pg_stat_activity like so:

SELECT pid, state, backend_start, substr(query, 0, 100) q
FROM pg_stat_activity
WHERE backend_type = 'client backend' AND query LIKE 'ALTER TABLE%'
ORDER BY backend_start;

With the blocked pid, you can use this query with pg_blocking_pids to generate SQL to terminate the blocking processes:

SELECT 'SELECT pg_terminate_backend(' || pid || ');'
FROM pg_stat_activity
WHERE pid = ANY (pg_blocking_pids(blockedpid));

To run this query, replace blockedpid with the pid of the blocked process. Then copy-paste the output lines and run them.

Connections Open Longer Than N Seconds

A final example: how to filter out connections to those open longer than N seconds. This is quite the blunt hammer, but you may try it in emergencies.

SELECT 'SELECT pg_terminate_backend(' || pid || ');'
FROM pg_stat_activity
WHERE backend_type = 'client backend'
      AND pid != pg_backend_pid()
      AND backend_start < NOW() - '10 seconds'::interval;

Adjust '10 seconds' as appropriate.


Find a query with his pid.

SELECT substr(query, 0, 5000) q
FROM pg_stat_activity
WHERE pid= '<pid>';


Les commentaires sont fermés.