Postgresql - Why is DROP VIEW command hanging?

I had a similar problem but the accepted answer didn't work for me as I do not have admin access to kill any process. Instead, this is how I managed to solve the problem:

  1. Issue SELECT * FROM pg_stat_activity; to get the stats about the PostgreSQL activities.
  2. In query column, look for the queries that read from that view. You may choose to narrow down your search by only looking into the rows related to your username (using username column) or query_start if you know when the issue emerged. There could be more than one row associated with your unwanted view.
  3. Identify all pid from the rows in the above step and plug them into SELECT pg_terminate_backend(<pid>); (instead of <pid>) one by one and run them.

Now you should be able to drop your view.

Please note that as you terminate the backend processes using pg_terminate_backend(), you may face some errors. The reason is that terminating some process may automatically end other processes. Therefore, some of the identified PIDs might be invalid by the time.


Finally I figure out what was wrong. Here are the steps to find the root cause:

Solution

Step 1 : List requested locks not granted

select * from pg_locks where not granted;

In my case, an attempt to lock, with the mode AccessExclusiveLock, the view I want to drop was not granted. This is why my DROP VIEW... hangs.

Step 2 : Find which other process(es) held a conflicting lock

select * from pg_locks where relation = <oid_of_view>

Here I list all processes locking or trying to lock on my view. I found out two processes, the one that want to drop the view and... another one.

Step 3 : Find out what other process(es) is/are doing now

select xact_start,query_start,backend_start,state_change,state from pg_stat_activity where pid in (<list_of_other_process(es)_pid>);

I had only one process holding a lock in my case. Surprisingly, its state was : idle in transaction

I was not able to drop the view because another process was idle in transaction. I simply kill it to solve my issue. For example, if the procpid was 8484 and let's suppose my postgresql server runs on a Linux box, then in the shell, I execute the following command:

$ kill -9 8484

Discussion

If you face similar issue, you can quickly find out what's going on by reproducing steps 1,2,3. You may need to customize Step 2 in order to find other conflicting process(es).

References

  • Lock Monitoring
  • Lock Dependency Information
  • View Postgresql Locks