Category Archives: performance tuning -postgresDba
pg_terminate_backend() to kill a connection in postgreSql
SELECT
pg_terminate_backend(pid)
FROM
pg_stat_activity
WHERE
— don’t kill my own connection!
pid pg_backend_pid()
— don’t kill the connections to other databases
AND datname = ‘database_name’
;
Before executing this query, you have to REVOKE the CONNECT privileges to avoid new connections:
REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;
If you’re using Postgres 8.4-9.1 use procpid instead of pid
SELECT
pg_terminate_backend(procpid)
FROM
pg_stat_activity
WHERE
— don’t kill my own connection!
procpid pg_backend_pid()
— don’t kill the connections to other databases
AND datname = ‘database_name’
;
Cancel query as non-superuser in postgreSQL
thedb=> SELECT * FROM pg_stat_activity WHERE procpid = 45678;
-[ RECORD 1 ]—-+——————————————————————-
datid | 596281
datname | thedb
procpid | 45678
usesysid | 596282
usename | myuser
application_name | QGIS
client_addr | 1.2.3.4
client_hostname |
client_port | 12345
backend_start | 2015-04-16 13:45:27.482691+12
xact_start | 2015-04-16 14:17:34.633156+12
query_start | 2015-04-16 14:17:34.633665+12
waiting | f
current_query | UPDATE …
But they can’t stop it:
thedb=> SELECT pg_terminate_backend(45678);
ERROR: must be superuser to signal other server processes
solution
You must either be the superuser or logged in as the same user who owns the session you wish to cancel.
So connect as user myuser and you’ll be able to pg_cancel_backend, or, if that doesn’t respond, pg_terminate_backend.
Terminate PostgreSQL sessions
problems:-
Sometimes you need to terminate connections initiated by badly behaving client application, or just make sure nobody is querying database during a major update.
The solution is to use pg_stat_activity view to identify and filter active database sessions and then use pg_terminate_backend function to terminate them.
To prevent access during an update process or any other important activity you can simply revoke connect permission for selected database users or alter pg_database system table.
Who is permitted terminate connections:-
Every database role with superuser rights is permitted to terminate database connections.
How to display database sessions
pg_stat_activity system view provides detailed information about server processes.
SELECT datname as database,
procpid as pid,
usename as username,
application_name as application,
client_addr as client_address,
current_query
FROM pg_stat_activity
Sample output that will be used in the following examples.
database | pid | username | application | client_address | current_query
———-+——+———-+————-+—————-+——————————————————————————————————————————————————————-
blog | 8603 | blog | blog_app | 192.168.3.11 | select * from posts order by pub_date
postgres | 8979 | postgres | psql | | select datname as database,procpid as pid,usename as username,application_name as application, client_addr as client_address, current_query from pg_stat_activity
wiki | 8706 | wiki | wiki_app | 192.168.3.8 |
(3 rows)
How to terminate all connections to the specified database
Use the following query to terminate all connections to the specified database.
SELECT pg_terminate_backend(procpid)
FROM pg_stat_activity
WHERE datname = ‘wiki’
current PostgreSQL queries View
SELECT datname,usename,procpid,client_addr,waiting,query_start,current_query FROM pg_stat_activity ;
Configuration
Storing of query strings is usually disabled in PostgreSQL by default. To enable it, use this line in your postgresql.conf
stats_command_string = true
This setting can be changed on a running database without restarting or effecting open connections by telling the PostgreSQL parent process, postmaster, to reload its config. Send it a SIGHUP or use the safer pg_ctl command with the reload option. Example:
pg_ctl reload
Queries
When stats_command_string is enabled the pg_stat_activity table holds all currently active query strings. The simplest query will show all current query strings along with which database they refer to and the process ID (PID) of the process serving that query.
SELECT datname,procpid,current_query FROM pg_stat_activity
Example:
database1=# SELECT datname,procpid,current_query FROM pg_stat_activity ORDER BY procpid ;
datname | procpid | current_query
—————+———+—————
mydatabaseabc | 2587 |
anotherdb | 15726 | SELECT * FROM users WHERE id=123 ;
mydatabaseabc | 15851 |
(3 rows)
Each row of pg_stat_activity represents one PostgreSQL process (PostgreSQL uses one server process per connection).Any processes that are not currently performing any queries will show as the current_query.
Note that queries from all databases within the server will be shown. If the user querying pg_stat_activity does not have privileges to access a database then it will not show the current_query.
The query_start column can also be used to show when the query started executing.
Another of my favourite queries is to show a top-like view of current queries, grouped by how many of the same query are running at that instant and the usernames belonging to each connection.
SELECT count(*) as cnt, usename, current_query FROM pg_stat_activity GROUP BY usename,current_query ORDER BY cnt DESC;
Example:
database1=# SELECT count(*) as cnt, usename, current_query FROM pg_stat_activity GROUP BY usename,current_query ORDER BY cnt DESC;
cnt | usename | current_query
—–+—————+—————
7 | freddykrueger |
3 | freddykrueger | SELECT name FROM users WHERE id=50;
1 | postgres |
(3 rows)
Show blocking Postgres processes and kill them in PostgreSql
There is a very nice way to show currently blocked queries and the processes those are blocking on slightly adapted from this query posted on the Postgres mailing list. I suggest putting it into a view so you can easily access it when you need it:
CREATE VIEW blocking_procs AS
SELECT
kl.pid as blocking_pid,
ka.usename as blocking_user,
ka.current_query as blocking_query,
bl.pid as blocked_pid,
a.usename as blocked_user,
a.current_query as blocked_query,
to_char(age(now(), a.query_start),’HH24h:MIm:SSs’) as age
FROM pg_catalog.pg_locks bl
JOIN pg_catalog.pg_stat_activity a
ON bl.pid = a.procpid
JOIN pg_catalog.pg_locks kl
ON bl.locktype = kl.locktype
and bl.database is not distinct from kl.database
and bl.relation is not distinct from kl.relation
and bl.page is not distinct from kl.page
and bl.tuple is not distinct from kl.tuple
and bl.virtualxid is not distinct from kl.virtualxid
and bl.transactionid is not distinct from kl.transactionid
and bl.classid is not distinct from kl.classid
and bl.objid is not distinct from kl.objid
and bl.objsubid is not distinct from kl.objsubid
and bl.pid kl.pid
JOIN pg_catalog.pg_stat_activity ka
ON kl.pid = ka.procpid
WHERE kl.granted and not bl.granted
ORDER BY a.query_start;
How to test the query on a testing server (not your production DB server)
Connect to your database open a transaction and manually lock a table:
BEGIN;
LOCK your_table;
Leave the transaction and connection open.
Open another client that accesses that data:
# SELECT count(*) from your_table;
It now should be blocked.
View the currently held locks with a third client
# SELECT * FROM blocking_procs;
blocking_pid | 25842
blocking_user | postgres
blocking_query | in transaction
blocked_pid | 25844
blocked_user | postgres
blocked_query | SELECT COUNT(*) FROM “your_table”
age | 00h:00m:23s
It’s now possible to kill the offending process holding the lock using:
# SELECT pg_terminate_backend(25842);
This will kill the connection where you’ve set the lock and the open transaction is rolled back but it seems to leave everything else intact. The second client should now get the response from the server.
Check if your current database is connected to PgBouncer or not.
This was inspired by someone asking on the Perl DBD IRC channel if it was possible to easily tell if your current database handle (usually “$dbh”) is connected to PgBouncer or not. Since I’ve seen this question asked in other venues, I decided to take a crack at it.
There are actually two questions to be answered: (1) are we connected to PgBouncer, and if so, (2) what pool_mode is being run? The quickest and easiest way I found to answer the first question is to try and connect to a non-existent database. Normally, this is a FATAL message, as seen here:
$ psql testdb -p 5432
testdb=# \c ghostdb
FATAL: database “ghostdb” does not exist
Previous connection kept
testdb=#
However, a slightly different ERROR message is returned if the same thing is attempted while connected to PgBouncer:
$ psql testdb -p 6432
testdb=# \c ghostdb
ERROR: No such database: ghostdb
Previous connection kept
Thus, an ERROR will always indicate that you are connected to PgBouncer and not directly to Postgres, which will always issue a FATAL.
In the future, there will be an even simpler method. As of this writing, pgBouncer 1.6 has not been released, but it will have the ability to customize the application_name. This is a configurable session-level variable that is fairly new in Postgres. Andrew Dunstan wrote a patch which enables adding this to your pgbouncer.ini file:
application_name_add_host = 1
This will make PgBouncer modify the application_name to append some information to it such as the remote host, the remote port, and the local port. This is a feature many PgBouncer users will appreciate, as it offers an escape from the black hole of connection information that PgBouncer suffers from. Here is what it looks like on both a normal Postgres connection, and a PgBouncer connection. As you can see, this is an easier check than the “invalid database connection” check above:
Postgres:
$ psql testdb -p 5432 -c ‘show application_name’
application_name
——————
psql
PgBouncer:
$ psql testdb -p 6432 -c ‘show application_name’
application_name
——————————–
psql – unix(7882@gtsm.com):6432
## DBD::Pg connections to PgBouncer get a very similar change:
$ perl testme.tmp.pl –port 6432
app – unix(6772@gtsm.com):6432
Now we have answered question of “are we connected to PgBouncer or not?”. The next question is which pool mode we are in. There are three pool modes you can set for PgBouncer, which controls when your particular connection is returned to “the pool”. For “session” mode, you keep the same Postgres backend the entire time you are connected. For “transaction”, you keep the same Postgres backend until the end of a transaction. For “statement”, you may get a new Postgres backend after each statement.
First, we can check if we are connected to PgBouncer in a statement level pool mode by taking advantage of the fact that multi-statement transactions are prohibited. PgBouncer enforces this by intercepting any attempts to enter a transaction (e.g. by issuing a BEGIN command). A very PgBouncer specific error about “Long transactions not allowed” is issued back to the client like so:
$ psql testdb -p 6432
testdb=# begin;
ERROR: Long transactions not allowed
So, that takes care of detecting a pool_mode set to ‘statement’. The other two modes, transaction and session, will *not* give the same error. Thus, seeing that error indicates you are using a statement-level PgBouncer connection.
The next pool mode is “transaction”, which means that the server connection if released back to the pool at the end of a transaction. To figure out if we are in this mode, we take advantage of the fact that PgBouncer can be set to clean up the connection at the end of each transaction by issuing a specific command. By default, the command set by server_reset_query is DISCARD ALL, which invalidates any prepared statements, temporary tables, and other transaction-spanning, session-level items. Thus, our test will see if these session-level artifacts get discarded or not:
Direct Postgres:
$ psql testdb -p 5432
testdb=# prepare abc(int) as select $1::text;
PREPARE
testdb=# execute abc(1);
text
——
1
PgBouncer:
$ psql testdb -p 6432
testdb=# prepare abc(int) as select $1::text;
PREPARE
testdb=# execute abc(1);
ERROR: prepared statement “abc” does not exist
Keep in mind that there are no true “transactionless” commands in Postgres. Even though we did not use a BEGIN in the psql prompt above, each command is treated as its own mini-transaction. In the case of the PgBouncer connection, the prepare is immediately followed with a DISCARD ALL, which means that our prepared statement no longer exists. Hence, we have determined that we are using a transaction-level PgBouncer connection.
Unfortunately, not getting an error does not necessarily mean your PgBouncer is NOT in transaction mode! It could be that server_reset_query is empty, meaning that temporary artifacts are not discarded at the end of the transaction. In such a case, we can take advantage of the fact that PgBouncer will allow other clients to share in our current connection, and thus be able to see the temporary items. If we create a temporary table in one pgbouncer connection, then connect again as a new client, the temporary table will only show up if we are sharing sessions but not transactions. Easier shown than explained, I suspect:
Regular Postgres gets a fresh session:
$ psql test1 -p 5432
test1=# create temp table abc(a int);
CREATE TABLE
test1=# select * from abc;
(No rows)
test1=# ^Z ## (we suspend with CTRL-Z)
[2]+ Stopped psql test1 -p 5432
$ psql test1 -p 5432
test1=# select * from abc;
ERROR: relation “abc” does not exist
PgBouncer will re-use the same session:
$ psql test1 -p 6432
test1=# create temp table abc(a int);
CREATE TABLE
test1=# select * from abc;
(No rows)
test1=# ^Z
[2]+ Stopped psql test1 -p 6432
$ psql test1 -p 6432
test1=# select * from abc;
(No rows)
The final PgBouncer pool mode is “session”, and basically means the only advantage over a normal Postgres connection is the overhead to start up and connect to a new Postgres backend. Thus, the PgBouncer connections are only returned to the pool upon disconnection. The only way to tell if you are in this mode is by determining that you are *not* in the other two modes. 🙂
So, although PgBouncer is extremely transparent, there are some tricks to determine if you are connected to it, and at what pool_mode. If you can think of other (SQL-level!) ways to check, please let me know in the comments section.
without restarting the server-drop all connections in postgreSql
Method 1.
Depending on your version of postgresql you might run into a bug, that makes pg_stat_activity to omit active connections from dropped users. These connections are also not shown inside pgAdminIII.
If you are doing automatic testing (in which you also create users) this might be a probable scenario.
In this case you need to revert to queries like:
SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_get_activity(NULL::integer)
WHERE datid=(SELECT oid from pg_database where datname = ‘your_database’);
Method 2.
The query like this should help (assuming the database is named ‘db’):
select pg_terminate_backend(pid) from pg_stat_activity where datname=’db’;
pid used to be called procpid, so if you’re using a version of postgres older than 9.2 you could try the following:
select pg_terminate_backend(procpid) from pg_stat_activity where datname=’db’;
However you have to be a superuser to disconnect other users.
It might also be useful to REVOKE CONNECT ON DATABASE FROM PUBLIC or something similar, and then GRANT it afterward.
Method 3.
This can be used to “free” a database from client connections, so that you for example can rename it:
SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname=’current_db’;
ALTER DATABASE current_db RENAME TO old_db;
ALTER DATABASE new_db RENAME TO current_db;
Be aware that this might cause problematic behaviour to your client apps. Data actualy should not be currupted due to using transactions.
Method 4.
$ ps aux | grep DATABASE_NAME
51191
postgres: user DATABASE_NAME [local] idle
then kill the process
$ kill -9 51191
pg_cancel_backend vs pg_terminate_backend in postgresql
gpadmin=# select datname,usename,procpid,sess_id,current_query from pg_stat_activity ;
datname | usename | procpid | sess_id | current_query
———+—————+———+———+——————————————————————————
gpadmin | running_user1 | 24174 | 26 | insert into test_table values (generate_series(1,100000000000));
gpadmin | idle_user1 | 24285 | 27 |
gpadmin | gpadmin | 23494 | 21 | select datname,usename,procpid,sess_id,current_query from pg_stat_activity ;
3 rows)
2.pg_cancel_backend()
pg_cancel_backend (procpid from pg_stat_activity ) should be used when query is running, the function will not impact when the session is IDLE.
gpadmin=# select pg_cancel_backend(24174) ;
pg_cancel_backend
——————-
t
(1 row)
note:- Canceling the query may take some time depending on the cleanup/rollback of the transactions.
3.pg_terminate_backend()
pg_terminate_backend (procpid from pg_stat_activity) should be used for terminating IDLE sessions, avoid using them on an active query or where the session is not ..
gpadmin=# select pg_terminate_backend(24285) ;
pg_terminate_backend
———————-
t
(1 row)
4.State of pg_stat_activity after running the above two commands:
gpadmin=# select datname,usename,procpid,sess_id,current_query from pg_stat_activity ;
datname | usename | procpid | sess_id | current_query
———+—————+———+———+——————————————————————————
gpadmin | running_user1 | 24174 | 26 |
gpadmin | gpadmin | 23494 | 21 | select datname,usename,procpid,sess_id,current_query from pg_stat_activity ;
(2 rows)
The IDLE session that you have witnessed again above is after we have cancelled the query through pg_cancel_backend, the query has been cancelled by the function but the user session still is connected.