]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
doc: Add new section describing fast-path locking
authorMichael Paquier <michael@paquier.xyz>
Wed, 1 Jul 2026 01:08:26 +0000 (10:08 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 1 Jul 2026 01:08:26 +0000 (10:08 +0900)
Fast-path locking is referenced by pg_stat_lock.fastpath_exceeded, by
pg_locks.fastpath, and in the GUC max_locks_per_transaction.  However,
the documentation has never described in details how this works; one
would need to look at the internals of lock.c, mostly around
EligibleForRelationFastPath().

This commit adds a new subsection called "Fast-Path Locking" to the area
dedicated to locks, with the three places mentioned above linking to it.

Author: Tatsuya Kawata <kawatatatsuya0913@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAHza6qdKo9dcPy70QBi88vpqhS2gYWViS8=Uj=-+QQbR=ONgSQ@mail.gmail.com

doc/src/sgml/config.sgml
doc/src/sgml/monitoring.sgml
doc/src/sgml/mvcc.sgml
doc/src/sgml/system-views.sgml

index 569fc0e7dbaa6177fcbc4d48d5116d631e86974e..6a0bb6d1344f76ecb845b26e0a52e05d74293ac7 100644 (file)
@@ -11726,6 +11726,12 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
         many children.  This parameter can only be set at server start.
        </para>
 
+       <para>
+        This parameter also determines the number of per-backend slots
+        available for <link linkend="locking-tables-fast-path">fast-path
+        locking</link>.
+       </para>
+
        <para>
         When running a standby server, you must set this parameter to have the
         same or higher value as on the primary server. Otherwise, queries
index 05bd501c6822a046f475e345dd74219592366ac4..2ec2bdd000bce64699cb66f8294b362aa94cd5e2 100644 (file)
@@ -3378,6 +3378,9 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         Number of times a lock of this type could not be acquired via fast path
         because the fast path slot limit was exceeded. Increasing
         <xref linkend="guc-max-locks-per-transaction"/> can reduce this number.
+        See <xref linkend="locking-tables-fast-path"/> for which locks are
+        eligible for fast-path locking; for ineligible lock types this
+        counter is always zero.
        </para>
       </entry>
      </row>
index 241caeb3593b9b5bec89c9e4fde0595bf2e668dc..9cb52302f23b5abae7efd3c6e25a5cb640181eef 100644 (file)
@@ -1248,6 +1248,44 @@ ERROR:  could not serialize access due to read/write dependencies among transact
       </tbody>
      </tgroup>
     </table>
+
+    <sect3 id="locking-tables-fast-path">
+     <title>Fast-Path Locking</title>
+
+     <indexterm zone="locking-tables-fast-path">
+      <primary>fast-path locking</primary>
+     </indexterm>
+
+     <para>
+      Internally, <productname>PostgreSQL</productname> can record some
+      table-level locks using a <firstterm>fast-path locking</firstterm>
+      mechanism instead of the main lock table. This reduces the overhead of
+      acquiring and releasing locks that rarely conflict. It is an
+      implementation optimization and does not change lock semantics.
+     </para>
+
+     <para>
+      Fast-path locking can be used only for eligible relation locks in the
+      weak table-level lock modes <literal>ACCESS SHARE</literal>
+      (<literal>AccessShareLock</literal>), <literal>ROW SHARE</literal>
+      (<literal>RowShareLock</literal>), and <literal>ROW EXCLUSIVE</literal>
+      (<literal>RowExclusiveLock</literal>). It does not apply to shared
+      relations (those visible across all databases, such as
+      <structname>pg_authid</structname>). Other lock types, and stronger
+      lock modes on relations, always go through the main lock table.  Even
+      for eligible locks, fast-path is used only when a per-backend slot is
+      available; the number of slots is derived from <xref
+      linkend="guc-max-locks-per-transaction"/>. When no slot is available,
+      the lock is acquired via the main lock table instead.
+     </para>
+
+     <para>
+      Acquiring a lock via the main lock table is considerably more
+      expensive than the fast path, and under heavy concurrent lock
+      activity can become a point of contention (observable as the
+      <literal>LockManager</literal> wait event).
+     </para>
+    </sect3>
    </sect2>
 
    <sect2 id="locking-rows">
index 2ebec6928d5de6cea17ab03ca6892a1217ff0888..5ea19d686221fa2731155d867a9d9ccab34908b6 100644 (file)
@@ -1977,7 +1977,7 @@ AND c1.path[c2.level] = c2.path[c2.level];
       </para>
       <para>
        True if lock was taken via fast path, false if taken via main
-       lock table
+       lock table (see <xref linkend="locking-tables-fast-path"/>)
       </para></entry>
      </row>
 
@@ -2113,7 +2113,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
    The <structname>pg_locks</structname> view displays data from both the
    regular lock manager and the predicate lock manager, which are
    separate systems; in addition, the regular lock manager subdivides its
-   locks into regular and <firstterm>fast-path</firstterm> locks.
+   locks into regular and <firstterm>fast-path</firstterm> locks
+   (see <xref linkend="locking-tables-fast-path"/>).
    This data is not guaranteed to be entirely consistent.
    When the view is queried,
    data on fast-path locks (with <structfield>fastpath</structfield> = <literal>true</literal>)