Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgres Database locked: Queries running forever

Tags:

postgresql

One of my python scripts ran some ALTER TABLE queries on the Postgres database. Something wrong happened and the tables got locked. When I run any query on any of those tables, it tells me Query Running and nothing happens. Currently, I am able to remove this lock only by shutting down my system and restarting it. Please tell me a better method. This is a Windows host.

like image 754
user3422637 Avatar asked Oct 27 '14 20:10

user3422637


People also ask

How do I stop locking in PostgreSQL?

To avoid deadlocks, make sure all transactions acquire locks on the same objects in the same order, and if multiple lock modes are involved for a single object, then transactions should always acquire the most restrictive mode first.

What is the default lock timeout in Postgres?

A value of zero (the default) disables the timeout. Unlike statement_timeout, this timeout can only occur while waiting for locks. Note that if statement_timeout is nonzero, it is rather pointless to set lock_timeout to the same or larger value, since the statement timeout would always trigger first.

How do I stop a running query in PostgreSQL?

The pg_cancel_backend() function is used to simply cancel out the query of a database using the process ID for a particular query. It doesn't terminate the database connection. While the pg_terminate_backend() function cancels the query using the process ID for the query and shuts the connected database.

How do I find Postgres blocked Sessions?

The pg_blocking_pids() function is a useful shortcut to find the database connections / sessions that are blocking another session. The pg_blocking_pids() function returns an postgreSQL array of PIDs that are blocking the specified server process PID that you provide to the query.


2 Answers

You should check for locks:

SELECT l.*,a.*
  FROM pg_locks l
  JOIN pg_stat_activity a USING (pid)
 WHERE NOT granted;

You'll see a list of waiting sessions. And the following:

SELECT l.*,a.*
  FROM pg_locks l
  JOIN pg_stat_activity a USING (pid)
 WHERE granted
   AND (database,relation) IN (SELECT database,relation
                                 FROM pg_locks WHERE NOT granted);

will give you a list of blocking sessions. If you use psql, use expanded output to get column-per-row output, better to view such information.

The following SQL script will display blocking tree (if there are blocked sessions), sessions on the top of each branch (yes, quite often there're several branches) will be the blocking ones.

I advise you to also have a look at this wiki page and this question: Postgresql DROP TABLE doesn't work (though it speaks bout DROP TABLE there, it might help).

In your case, I recommend to identify blocking sessions and try to find out why they're blocking. Most typical case in my experience — somebody forgot to press enter after COMMIT and went out for lunch. If you're sure this will not hurt your system, you can kill blocking session:

SELECT pg_terminate_backend(pid);
like image 71
vyegorov Avatar answered Sep 20 '22 05:09

vyegorov


Reference taken from this article. Find blocking sessions:

    SELECT 
        pl.pid as blocked_pid
        ,psa.usename as blocked_user
        ,pl2.pid as blocking_pid
        ,psa2.usename as blocking_user
        ,psa.query as blocked_statement
    FROM pg_catalog.pg_locks pl
    JOIN pg_catalog.pg_stat_activity psa
        ON pl.pid = psa.pid
    JOIN pg_catalog.pg_locks pl2
    JOIN pg_catalog.pg_stat_activity psa2
        ON pl2.pid = psa2.pid
        ON pl.transactionid = pl2.transactionid 
            AND pl.pid != pl2.pid
    WHERE NOT pl.granted;
like image 22
Anvesh Avatar answered Sep 20 '22 05:09

Anvesh