From dc60d6aa1eba67361ee0f91fec2fa6af7f9db3b9 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 5 Oct 2026 14:52:18 -0500 Subject: [PATCH] Fix pg_blocking_pids() for relation extension locks. pg_blocking_pids() assumes that members of the same lock group never block each other, but that hasn't been true for relation extension locks since v13. This commit teaches the function to report lock group members as blockers for relation extension locks. Since parallel workers are reported with their leader's PID, the result may now include the blocked session's own PID. Oversight in commit 85f6b49c2c. Author: Bertrand Drouvot Reviewed-by: Chao Li Reviewed-by: Kirill Reshke Reviewed-by: Shihao Zhong Discussion: https://postgr.es/m/apTpV8h%2BCYHf%2B1PJ%40bdtpg Backpatch-through: 14 --- doc/src/sgml/func.sgml | 21 ++++++++++++++------- src/backend/utils/adt/lockfuncs.c | 10 ++++++++-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 1eb9f48cb25..c7d96fd6bc2 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -25009,13 +25009,20 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n); One server process blocks another if it either holds a lock that conflicts with the blocked process's lock request (hard block), or is waiting for a lock that would conflict with the blocked process's lock - request and is ahead of it in the wait queue (soft block). When using - parallel queries the result always lists client-visible process IDs - (that is, pg_backend_pid results) even if the - actual lock is held or awaited by a child worker process. As a result - of that, there may be duplicated PIDs in the result. Also note that - when a prepared transaction holds a conflicting lock, it will be - represented by a zero process ID. + request and is ahead of it in the wait queue (soft block). A prepared + transaction that holds a conflicting lock is represented by a zero + process ID. + + + When using parallel queries the result always lists client-visible + process IDs (that is, pg_backend_pid results) + even if the actual lock is held or awaited by a child worker process. + As a result of that, there may be duplicated PIDs in the result. Note + that the processes of a parallel query can block each other on + relation extension locks (lock type extend in + pg_locks), + in which case the result contains the blocked session's own process + ID. Frequent calls to this function could have some impact on database diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 00e67fb46d0..ce0f201f85d 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -517,8 +517,14 @@ pg_blocking_pids(PG_FUNCTION_ARGS) /* A proc never blocks itself, so ignore that entry */ if (instance == blocked_instance) continue; - /* Members of same lock group never block each other, either */ - if (instance->leaderPid == blocked_instance->leaderPid) + + /* + * Members of the same lock group don't block each other, either, + * except on relation extension locks (see LockCheckConflicts()). + */ + if (instance->leaderPid == blocked_instance->leaderPid && + blocked_instance->locktag.locktag_type != + LOCKTAG_RELATION_EXTEND) continue; if (conflictMask & instance->holdMask)