-<!-- $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>
</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>
-<!-- $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>
<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>
(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 — 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 > 12345 LIMIT 100; -- danger!
+SELECT pg_advisory_lock(q.id) FROM
+(
+ SELECT id FROM foo WHERE id > 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">
</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>