diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-09-20 23:43:22 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-09-20 23:43:22 +0000 |
commit | 0efa510bf7c762e1e3ff585d91f9ca51817e65b2 (patch) | |
tree | 858249c2d6318cb12ade3b4b75a5431ade3d52c0 | |
parent | e56ccad7b06e2b3a0655d7879a108333704c1197 (diff) | |
download | postgresql-0efa510bf7c762e1e3ff585d91f9ca51817e65b2.tar.gz postgresql-0efa510bf7c762e1e3ff585d91f9ca51817e65b2.zip |
Add documentation for new in-core advisory lock functions. Merlin Moncure
-rw-r--r-- | doc/src/sgml/func.sgml | 200 | ||||
-rw-r--r-- | doc/src/sgml/mvcc.sgml | 108 |
2 files changed, 290 insertions, 18 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 224b9005dec..3c956ad8eb3 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -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> diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index 2dd3f993725..ef8675b3a4e 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -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> @@ -25,10 +25,10 @@ </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 @@ -36,7 +36,10 @@ 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 — 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"> @@ -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> |