]> granicus.if.org Git - postgresql/commitdiff
Add documentation for new in-core advisory lock functions. Merlin Moncure
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 20 Sep 2006 23:43:22 +0000 (23:43 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 20 Sep 2006 23:43:22 +0000 (23:43 +0000)
doc/src/sgml/func.sgml
doc/src/sgml/mvcc.sgml

index 224b9005decf0ff5f8072733d4ca574656a6b98c..3c956ad8eb3abde8335b155e0e62c1d679a7cacb 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.338 2006/09/16 00:30:13 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.339 2006/09/20 23:43:21 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -10577,15 +10577,205 @@ postgres=# select * from pg_xlogfile_name_offset(pg_stop_backup());
    </indexterm>
    <para>
     <function>pg_stat_file</> returns a record containing the file
-    size, last accessed time stamp, last modified time stamp, 
-    last file status change time stamp (Unix platforms only), 
-    file creation timestamp (Windows only), and a <type>boolean</type> indicating 
-    if it is a directory.  Typical usages include:
+    size, last accessed time stamp, last modified time stamp,
+    last file status change time stamp (Unix platforms only),
+    file creation timestamp (Windows only), and a <type>boolean</type>
+    indicating if it is a directory.  Typical usages include:
 <programlisting>
 SELECT * FROM pg_stat_file('filename');
 SELECT (pg_stat_file('filename')).modification;
 </programlisting>
    </para>
 
+   <para>
+    The functions shown in <xref linkend="functions-advisory-locks"> manage
+    advisory locks.  For details about proper usage of these functions, see
+    <xref linkend="advisory-locks">.
+   </para>
+
+   <table id="functions-advisory-locks">
+    <title>Advisory Lock Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain exclusive advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain exclusive advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain shared advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain shared advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain exclusive advisory lock if available</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain exclusive advisory lock if available</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain shared advisory lock if available</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain shared advisory lock if available</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release an exclusive advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release an exclusive advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release a shared advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release a shared advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_all</function>()</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Release all advisory locks held by the current session</entry>
+      </row>
+
+     </tbody>
+    </tgroup>
+   </table>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_lock</primary>
+   </indexterm>
+   <para>
+    <function>pg_advisory_lock</> locks an application-defined resource,
+    which may be identified either by a single 64-bit key value or two
+    32-bit key values (note that these two key spaces do not overlap).  If
+    another session already holds a lock on the same resource, the
+    function will wait until the resource becomes available.  The lock
+    is exclusive.  Multiple lock requests stack, so that if the same resource
+    is locked three times it must be also unlocked three times to be
+    released for other sessions' use.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_lock_shared</primary>
+   </indexterm>
+   <para>
+    <function>pg_advisory_lock_shared</> works the same as
+    <function>pg_advisory_lock</>,
+    except the lock can be shared with other sessions requesting shared locks.
+    Only would-be exclusive lockers are locked out.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_try_advisory_lock</primary>
+   </indexterm>
+   <para>
+    <function>pg_try_advisory_lock</> is similar to
+    <function>pg_advisory_lock</>, except the function will not wait for the
+    lock to become available.  It will either obtain the lock immediately and
+    return <literal>true</>, or return <literal>false</> if the lock cannot be
+    acquired now.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_try_advisory_lock_shared</primary>
+   </indexterm>
+   <para>
+    <function>pg_try_advisory_lock_shared</> works the same as
+    <function>pg_try_advisory_lock</>, except it attempts to acquire
+    shared rather than exclusive lock.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock</primary>
+   </indexterm>
+   <para>
+    <function>pg_advisory_unlock</> will release a previously-acquired
+    exclusive advisory lock.  It
+    will return <literal>true</> if the lock is successfully released.
+    If the lock was in fact not held, it will return <literal>false</>,
+    and in addition, an SQL warning will be raised by the server.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock_shared</primary>
+   </indexterm>
+   <para>
+    <function>pg_advisory_unlock_shared</> works the same as
+    <function>pg_advisory_unlock</>, 
+    except to release a shared advisory lock.
+   </para>
+
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock_all</primary>
+   </indexterm>
+   <para>
+    <function>pg_advisory_unlock_all</> will release all advisory locks
+    held by the current session.  (This function is implicitly invoked
+    at session end, even if the client disconnects ungracefully.)
+   </para>
+
   </sect1>
 </chapter>
index 2dd3f993725614f633bcbf5348e46d607f81f072..ef8675b3a4ef8a18e0b902930d9700bba0d5e3e8 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.62 2006/09/18 12:11:36 teodor Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.63 2006/09/20 23:43:22 tgl Exp $ -->
 
  <chapter id="mvcc">
   <title>Concurrency Control</title>
    </indexterm>
 
    <para>
-    Unlike traditional database systems which use locks for concurrency control,
-    <productname>PostgreSQL</productname>
-    maintains data consistency by using a multiversion model
-    (Multiversion Concurrency Control, <acronym>MVCC</acronym>). 
+    <productname>PostgreSQL</productname> provides a rich set of tools 
+    for developers to manage concurrent access to data.  Internally,
+    data consistency is maintained by using a multiversion 
+    model (Multiversion Concurrency Control, <acronym>MVCC</acronym>). 
     This means that while querying a database each transaction sees
     a snapshot of data (a <firstterm>database version</firstterm>)
     as it was some
     This protects the transaction from viewing inconsistent data that
     could be caused by (other) concurrent transaction updates on the same
     data rows, providing <firstterm>transaction isolation</firstterm>
-    for each database session.
+    for each database session.  <acronym>MVCC</acronym>, by eschewing
+    explicit locking methodologies of traditional database systems,
+    minimizes lock contention in order to allow for reasonable 
+    performance in multiuser environments.
    </para>
 
    <para>
@@ -52,7 +55,9 @@
     <productname>PostgreSQL</productname> for applications that cannot
     adapt easily to <acronym>MVCC</acronym> behavior.  However, proper
     use of <acronym>MVCC</acronym> will generally provide better
-    performance than locks.
+    performance than locks.  In addition, application-defined advisory
+    locks provide a mechanism for acquiring locks that are not tied
+    to a single transaction.
    </para>
   </sect1>
 
@@ -859,6 +864,83 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
      (e.g., while waiting for user input).
     </para>
    </sect2>
+
+   <sect2 id="advisory-locks">
+    <title>Advisory Locks</title>
+
+    <indexterm zone="advisory-locks">
+     <primary>lock</primary>
+     <secondary>advisory</secondary>
+    </indexterm>
+
+    <para>
+     <productname>PostgreSQL</productname> provides a means for
+     creating locks that have application-defined meanings.  These are
+     called <firstterm>advisory locks</>, because the system does not
+     enforce their use &mdash; it is up to the application to use them
+     correctly.  Advisory locks can be useful for locking strategies
+     that are an awkward fit for the MVCC model.  Once acquired, an
+     advisory lock is held until explicitly released or the session ends.
+     Unlike standard locks, advisory locks do not
+     honor transaction semantics.  For example, a lock acquired during a
+     transaction that is later rolled back will still be held following the
+     rollback.  The same lock can be acquired multiple times by its
+     owning process: for each lock request there must be a corresponding
+     unlock request before the lock is actually released.  (If a session
+     already holds a given lock, additional requests will always succeed, even
+     if other sessions are awaiting the lock.)  Like all locks in
+     <productname>PostgreSQL</productname>, a complete list of advisory
+     locks currently held by any session can be found in the system view
+     <structname>pg_locks</structname>.
+    </para>
+
+    <para>
+     Advisory locks are allocated out of a shared memory pool whose size
+     is defined by the configuration variables
+     <xref linkend="guc-max-locks-per-transaction"> and
+     <xref linkend="guc-max-connections">.
+     Care must be taken not to exhaust this
+     memory or the server will not be able to grant any locks at all.
+     This imposes an upper limit on the number of advisory locks
+     grantable by the server, typically in the tens to hundreds of thousands
+     depending on how the server is configured.
+    </para>
+
+    <para>
+     A common use of advisory locks is to emulate pessimistic locking
+     strategies typical of so called <quote>flat file</> data management
+     systems.
+     While a flag stored in a table could be used for the same purpose,
+     advisory locks are faster, avoid MVCC bloat, and are automatically
+     cleaned up by the server at the end of the session.
+     In certain cases using this method, especially in queries
+     involving explicit ordering and <literal>LIMIT</> clauses, care must be
+     taken to control the locks acquired because of the order in which SQL
+     expressions are evaluated.  For example:
+<screen>
+SELECT pg_advisory_lock(id) FROM foo WHERE id = 12345; -- ok
+SELECT pg_advisory_lock(id) FROM foo WHERE id &gt; 12345 LIMIT 100; -- danger!
+SELECT pg_advisory_lock(q.id) FROM
+(
+  SELECT id FROM foo WHERE id &gt; 12345 LIMIT 100;
+) q; -- ok
+</screen>
+     In the above queries, the second form is dangerous because the
+     <literal>LIMIT</> is not guaranteed to be applied before the locking
+     function is executed.  This might cause some locks to be acquired
+     that the application was not expecting, and hence would fail to release
+     (until it ends the session).
+     From the point of view of the application, such locks
+     would be dangling, although still viewable in
+     <structname>pg_locks</structname>.
+    </para>
+
+    <para>
+     The functions provided to manipulate advisory locks are described in
+     <xref linkend="functions-advisory-locks">.
+    </para>
+   </sect2>
+
   </sect1>
 
   <sect1 id="applevel-consistency">
@@ -993,12 +1075,12 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
       </term>
       <listitem>
        <para>
-               Short-term share/exclusive page-level locks are used for 
-               read/write access. Locks are released immediately after each
-               index row is fetched or inserted. But note that a GIN-indexed
-               value insertion usually produces several index key insertions
-               per row, so GIN may do substantial work for a single value's
-               insertion.
+        Short-term share/exclusive page-level locks are used for
+        read/write access. Locks are released immediately after each
+        index row is fetched or inserted. But note that a GIN-indexed
+        value insertion usually produces several index key insertions
+        per row, so GIN may do substantial work for a single value's
+        insertion.
        </para>
       </listitem>
      </varlistentry>