1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

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 <bertranddrouvot.pg@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Shihao Zhong <zhong950419@gmail.com>
Discussion: https://postgr.es/m/apTpV8h%2BCYHf%2B1PJ%40bdtpg
Backpatch-through: 14
This commit is contained in:
Nathan Bossart
2026-10-05 14:52:18 -05:00
parent 90cc09f57f
commit dc60d6aa1e
2 changed files with 22 additions and 9 deletions

View File

@@ -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, <function>pg_backend_pid</function> 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.
</para>
<para>
When using parallel queries the result always lists client-visible
process IDs (that is, <function>pg_backend_pid</function> 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 <literal>extend</literal> in
<link linkend="view-pg-locks"><structname>pg_locks</structname></link>),
in which case the result contains the blocked session's own process
ID.
</para>
<para>
Frequent calls to this function could have some impact on database

View File

@@ -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)