How to kill queries which theirs processes are no longer exists - postgresql

I run:
select *
from pg_stat_activity
And there are some old queries (which still run on the DB background) which theirs python application doesn't exists (The apps crash or stopped without calling connection close command)
State wait_event backend_type
Active null parallel_backend
Is there a way to close all the queries which theirs processes are no longer exists ?
I saw this post:
Kill a postgresql session/connection
but I don't want to kill all sessions or connections, because there are some connections which gather and update important data.
I just want to close sessions (and stop queries) which theirs processes are no longer exists.

If you know or able to figure it out which are not neccessary, then you can fetch their pids from here.
SELECT pid,* FROM pg_stat_activity;
And use those pids over here along with dbname to kill those connections.
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
where datname in (<put dbname over here>)
and pid in(<put pid over here>);
Or simply use the below query to kill idle connections, which are not active.
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
where datname in (<put dbname over here>')
and state = 'idle';

Related

How to Write PostgreSQL Stored Procedure to find and kill idle query?

Need to write PostgreSQL Stored Procedure to find and kill Idle queries. Below are the query to find and kill PID:
To find list of PID:
SELECT pid FROM pg_stat_activity where datname='dbdataanalytics' and state='idle' and state_change<=current_date-1
To kill The PID:
SELECT pg_terminate_backend(pid) FROM idle_connections
But I need to run this every day automatically. Please help me write stored procedure.
You should upgrade to PostgreSQL v14 and set the idle_session_timeout parameter. Even better would be to fix the connection leak in your application.
To terminate all connections that have been idle for more then 5 minutes, tun
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
AND state_change < current_timestamp - INTERVAL '5 minutes';

Do I have stuck queries?

I'm running the following query:
select *
from pg_stat_activity
and getting:
dataid dataname username waitevent query
16384 my_db pos12 clientRead query_1
16384 my_db pos12 clientRead query_2
16384 my_db pos12 clientRead query_3
where query_1, query_2, query_3 are some select queries
There are no applications which running and querying the database.
Does it mean that those queries are old stuck queries?
How can I know if there are old stuck queries?
Do stuck queries occupied DB resources?
Sessions that are in state ClientRead are idle, waiting for the next command from the client.
Whether that is a problem from the database side or not depends on the state:
if the state is idle, the session is not consuming any resources (save for some little memory) and is quite harmless
if the state is idle in transaction for a longer time, the sessions hold locks and block database maintenance – this would be an application bug that has to be fixed there
At any rate, if these are all your sessions, then the database is idle, and if anything is stuck, it is in the client side.

Canceling running queries from cli

I am looking for a way to cancel queries that are currently running from cli.
I have found these links:
https://www.postgresql.org/docs/11/libpq-cancel.html
https://www.postgresql.org/docs/11/contrib-dblink-cancel-query.html
but seems that it is not what I am looking for.
Given the pid of the session running the query (the process ID of the corresponding backend process, which you can find in pg_stat_activity, or from ps, top, etc.), you can use:
psql -c "SELECT pg_cancel_backend(<your_pid>)"
If you're trying to kill all queries meeting some criteria (e.g. those which have been running/blocking/idle for some period of time, or those running against a particular database), something like this is often useful:
psql -c "SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE <your_conditions>"
You can also disconnect them using pg_terminate_backend(pid).
To cancel the most recently started query:
SELECT pg_cancel_backend(pid)
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
ORDER BY query_start DESC
LIMIT 1;
pg_backend_pid() is the connection you're using to run the command; without this filter, the "latest query" would be the one you're currently executing.

How to relate a backend pid to a windows application?

I have postgres database that has two windows processes connected to it. One is a powershell script, the other is a c# application. Both processes run on the same box accessing the same database.
I have occasional locking problems, checking in pg_locks will give me the blocked and blocking pids.
If I look on windows task manager I can see that both of these pids have the process name 'postgres.exe'
How can I tell which pid refers to the poweshell process, and which to the c# app?
The app (or script) can tell you its pid using the function pg_backend_pid()
select pg_backend_pid();
Alternatively, you can set different application_name parameters in your apps and report this using pg_stat_activity, e.g.:
set application_name to 'my_distinct_name';
select l.*, a.application_name
from pg_locks l
join pg_stat_activity a using (pid);

Force client disconnect using PostgreSQL

Is there a way to force clients to disconnect from PostgreSQL? I'm looking for the equivlent of DB2's force application all.
I'd like to do this on my development box because when I've got database consoles open, I can't load a database dump. I have to quit them first.
Kills idle processes in PostgreSQL 8.4:
SELECT procpid, (SELECT pg_terminate_backend(procpid)) as killed from pg_stat_activity
WHERE current_query LIKE '<IDLE>';
Combine pg_terminate_backend function and the pg_stat_activity system view.
This SO answer beautifully explains (full quote from araqnid between the horizontal rules, then me again):
To mark database 'applogs' as not accepting new connections:
update pg_database set datallowconn = false where datname = 'applogs';
Another possibility would be to revoke 'connect' access on the database for the client role(s).
Disconnect users from database = kill backend. So to disconnect all other users from "applogs" database, for example:
select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'applogs' and procpid <> pg_backend_pid();
Once you've done both of those, you are the only user connected to 'applogs'. Although there might actually be a delay before the backends actually finish disconnecting?
Update from MarkJL: There is indeed a delay before the backends finish disconnecting.
Now me again: That being said, mind that the procpid column was renamed to pid in PostgreSQL 9.2 and later.
I think that this is much more helpful than the answer by Milen A. Radev which, while technically the same, does not come with usage examples and real-life suggestions.
I post my answer because I couldn't use any of them in my script, server 9.3:
psql -U postgres -c "SELECT pid, (SELECT pg_terminate_backend(pid)) as killed from pg_stat_activity WHERE datname = 'my_database_to_alter';"
In the next line, you can do anything yo want with 'my_database_to_alter'. As you can see, yo perform the query from the "postgres" database, which exists almost in every postgresql installation.
Doing by superuser and outside the problem-database itself worked perfect for me.
probably a more heavy handed approach then should be used but:
for x in `ps -eF | grep -E "postgres.*idle"| awk '{print $2}'`;do kill $x; done
I found this thread on the mailing list. It suggests using SIGTERM to cause the clients to disconnect.
Not as clean as db2 force application all.