PostgreSQL Lock Troubleshooting, Unlocking Blocked Processes

PostgreSQL Lock Troubleshooting: Unlocking Blocked Processes

In a busy PostgreSQL environment, transactions can sometimes become blocked, waiting for other transactions to release locks. This can slow performance and even cause stalls. This article dissects a powerful PostgreSQL script designed to expose blocked processes, offering insights to help you troubleshoot and optimize performance.

Sample Code from Command Line

 1SELECT
 2  blocked_locks.pid         AS blocked_pid,
 3  blocked_activity.usename  AS blocked_user,
 4  blocking_locks.pid        AS blocking_pid,
 5  blocking_activity.usename AS blocking_user,
 6  blocked_activity.query    AS blocked_statement,
 7  blocking_activity.query   AS current_statement_in_blocking_process
 8FROM
 9  pg_catalog.pg_locks AS blocked_locks
10JOIN
11  pg_catalog.pg_stat_activity AS blocked_activity
12ON
13  blocked_activity.pid = blocked_locks.pid
14JOIN
15  pg_catalog.pg_locks AS blocking_locks
16ON
17  blocking_locks.locktype = blocked_locks.locktype
18  AND blocking_locks.database       IS NOT DISTINCT FROM blocked_locks.database
19  AND blocking_locks.relation       IS NOT DISTINCT FROM blocked_locks.relation
20  AND blocking_locks.page           IS NOT DISTINCT FROM blocked_locks.page
21  AND blocking_locks.tuple          IS NOT DISTINCT FROM blocked_locks.tuple
22  AND blocking_locks.virtualxid     IS NOT DISTINCT FROM blocked_locks.virtualxid
23  AND blocking_locks.transactionid  IS NOT DISTINCT FROM blocked_locks.transactionid
24  AND blocking_locks.classid        IS NOT DISTINCT FROM blocked_locks.classid
25  AND blocking_locks.objid          IS NOT DISTINCT FROM blocked_locks.objid
26  AND blocking_locks.objsubid       IS NOT DISTINCT FROM blocked_locks.objsubid
27  AND blocking_locks.pid != blocked_locks.pid
28JOIN
29  pg_catalog.pg_stat_activity blocking_activity
30ON
31  blocking_activity.pid = blocking_locks.pid
32WHERE
33  NOT blocked_locks.granted;

Notes List PostgreSQL locks blocked. Requires PostgreSQL 9.2+. Tested on PostgreSQL 9.2+, 10.x, 11.x, 12.x, 13.0.

Code Breakdown:

  • Strategic Joins: Links multiple PostgreSQL system views:
    • pg_catalog.pg_locks: Core lock information.
    • pg_catalog.pg_stat_activity: Details on active processes.
  • Sophisticated Filtering: Joins use numerous conditions to ensure we're seeing relevant lock conflicts.
  • Output:
    • blocked_pid, blocking_pid: Process IDs of blocked and blocking transactions.
    • blocked_user, blocking_user: Associated usernames.
    • blocked_statement: Query the blocked process was trying to execute.
    • current_statement_in_blocking_process: Query the blocking process is currently running.

Purpose This script's primary purpose is to give you the precise details needed to investigate the cause of blocked processes in your PostgreSQL database.

Insights and Explanations

  • What's Blocking What: Understand which processes are holding resources others need, creating stalls.
  • Query Analysis: Examine the queries involved in a lock conflict. This can offer clues for optimization or restructuring logic.
  • Troubleshooting Starting Point: This isn't a fix, but rather an essential diagnostic tool. You'll then need to decide if killing long-running queries, changing isolation levels, etc. is needed. Insights and Explanations
  • Blocked vs. Blocking: Demystify the relationship between blocked and blocking processes.
  • Targeted Visibility: Pinpoint the specific transactions causing blockages.
  • Query Clues: See active queries involved in lock conflicts.
  • Troubleshooting Techniques: Gain strategies to address locked scenarios.

References:

PostgreSQL on Locks: https://www.postgresql.org/docs/current/explicit-locking.html

pg_stat_activity view: https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW

Lock Monitoring: https://wiki.postgresql.org/wiki/Lock_Monitoring

Source:

https://github.com/HariSekhon/SQL-scripts/blob/master/postgres_locks_blocked.sql