docs for advisory locks
ok, here is the promised docs for the advisory locks.
some quick notes here: this is my first non trivial patch (albeit only
documentation) and i am a complete docbook novice. i also dont have
the capability to build docbook at the moment. so consider this a
very rough draft. any comments are welcome particularly from someone
willing to build the sgml and check for errors...sorry about that but
i wanted to get this up as soon as possible.
thanks
merlin
Attachments:
advisory_docs.patchapplication/octet-stream; name=advisory_docs.patchDownload
? advisory_docs.patch
Index: src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.338
diff -u -p -r1.338 func.sgml
--- src/sgml/func.sgml 16 Sep 2006 00:30:13 -0000 1.338
+++ src/sgml/func.sgml 19 Sep 2006 18:19:56 -0000
@@ -10586,6 +10586,191 @@ 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>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_column_size</primary>
+ </indexterm>
+
+ <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <type>int</>)</literal>
+ </entry>
+ <entry><type>void</type></entry>
+ <entry>Obtain exclusive advisory lock if available</entry>
+ </row>
+
+ <row>
+ <entry>
+ <literal><function>pg_advisory_lock_shared</function>(<parameter>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>boolean</type></entry>
+ <entry>Releases 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
+ (either defined by value or a combination of value1 and value2). The
+ function will wait until the resource becomes available. The lock
+ is exclusive. The locks can stack so that if the same resource is
+ locked three times it must be also unlocked three times to be completely
+ released.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_lock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_lock_shared</> as <function>pg_advisory_lock</>,
+ except the lock can be shared with other sessions locking shared.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_try_advisory_lock</primary>
+ </indexterm>
+ <para>
+ <function>pg_try_advisory_lock</> as <function>pg_advisory_lock</>,
+ except the function will not wait until the lock is available. It will return
+ true if it is available (success) and false if it is not.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_try_advisory_lock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_try_advisory_lock_shared</> as
+ <function>pg_advisory_lock_shared</>, except the function will not wait
+ until the lock is available. It will return true if it is available
+ (success) and false if it is not.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_unlock</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock</> will release an exclude advisory lock. It
+ will return true if the lock is released. If no lock is available, it will
+ return false. In addition, an SQL warning will be raised by the backend.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_unlock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock_shared</> 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</> as will release all advisory locks
+ held by the current session.
+ </para>
</sect1>
</chapter>
Index: src/sgml/mvcc.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v
retrieving revision 2.62
diff -u -p -r2.62 mvcc.sgml
--- src/sgml/mvcc.sgml 18 Sep 2006 12:11:36 -0000 2.62
+++ src/sgml/mvcc.sgml 19 Sep 2006 18:19:57 -0000
@@ -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. Internal
+ integrity 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,11 @@
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 +56,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 scoped
+ to a transaction.
</para>
</sect1>
@@ -859,6 +865,66 @@ UPDATE accounts SET balance = balance -
(e.g., while waiting for user input).
</para>
</sect2>
+
+ <sect2 id="advisory-locks">
+ <title>Advisory Locks</title>
+
+ <indexterm zone="advisory-locks">
+ <primary>advisory</primary>
+ </indexterm>
+
+ <para>
+ <productname>PostgreSQL</productname> provides a means for
+ creating locks that have an application defined meaning, called
+ advisory locks. Advisory locks are suitable for locking strategies
+ that are an awkward fit for the MVCC model. They have a lifetime
+ that is scoped to the end of the session or the lock is released,
+ whichever is sooner. Unlike standard locks, advisory locks do not
+ honor transaction semantics. For example, a lock acquired during a
+ transaction that is rolled back will still be held following the
+ rollback. The same lock can be acquired multiple times by its
+ owning process: for each lock there must be a corresponding unlock
+ for the lock to be fully released. Like all locks in
+ <productname>PostgreSQL</productname>, a complete list of advisory
+ locks held by the system can be listed in the system catalog
+ <structname>pg_locks</structname>.
+ </para>
+
+ <para>
+ Advisory locks are allocated out of a shared buffer pool whose size
+ is defined by the configuration variables max_connections and
+ max_locks_per_transaction. Care must be given not to exhaust this
+ memory or the server will not be able to grant any locks at all.
+ This imposes an aper limit on the amount of advisory locks
+ grantable by the server in the tens or 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 'flat file' data management systems.
+ While a table based flag could be used for the same purpose,
+ advisory locks are faster, avoid MVCC bloat, and are cleaned up
+ by the server at the end of the session.
+ Integer based keys are especially well suited for this type of lock
+ management. In certain cases using this method, especially in queries
+ involving explicit ordering and limit, care must be given to control
+ the amount of locks required because of the order in which the SQL
+ expressions are evaluated. For example:
+<screen>
+SELECT pg_advisory_lock(id, 0, 0) FROM foo WHERE id = 12345; -- ok
+SELECT pg_advisory_lock(id, 0, 0) FROM foo WHERE id > 12345 LIMIT 100; -- danger!
+SELECT pg_advisory_lock(q.id, 0, 0) FROM
+(
+ select * foo WHERE id > 12345 LIMIT 100;
+) q; -- ok
+</screen>
+ In the above queries, the second form is dangerous because the limit
+ expression is not guaranteed to evaluate before the locking function.
+ In this case, from the point of view of the application, the locks
+ would be dangling, although still viewable in pg_locks.
+ </sect2>
+
</sect1>
<sect1 id="applevel-consistency">
[resending this to the list, was silently dropped this afternoon?]
---------- Forwarded message ----------
From: Merlin Moncure <mmoncure@gmail.com>
Date: Sep 19, 2006 11:57 PM
Subject: docs for advisory locks
To: pgsql-patches@postgresql.org
ok, here is the promised docs for the advisory locks.
some quick notes here: this is my first non trivial patch (albeit only
documentation) and i am a complete docbook novice. i also dont have
the capability to build docbook at the moment. so consider this a
very rough draft. any comments are welcome particularly from someone
willing to build the sgml and check for errors...sorry about that but
i wanted to get this up as soon as possible.
thanks
merlin
Attachments:
advisory_docs.patchapplication/octet-stream; name=advisory_docs.patchDownload
? advisory_docs.patch
Index: src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.338
diff -u -p -r1.338 func.sgml
--- src/sgml/func.sgml 16 Sep 2006 00:30:13 -0000 1.338
+++ src/sgml/func.sgml 19 Sep 2006 18:19:56 -0000
@@ -10586,6 +10586,191 @@ 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>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_column_size</primary>
+ </indexterm>
+
+ <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <type>int</>)</literal>
+ </entry>
+ <entry><type>void</type></entry>
+ <entry>Obtain exclusive advisory lock if available</entry>
+ </row>
+
+ <row>
+ <entry>
+ <literal><function>pg_advisory_lock_shared</function>(<parameter>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>value</> <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>value1</> <type>int</>, <parameter>value2</> <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>boolean</type></entry>
+ <entry>Releases 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
+ (either defined by value or a combination of value1 and value2). The
+ function will wait until the resource becomes available. The lock
+ is exclusive. The locks can stack so that if the same resource is
+ locked three times it must be also unlocked three times to be completely
+ released.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_lock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_lock_shared</> as <function>pg_advisory_lock</>,
+ except the lock can be shared with other sessions locking shared.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_try_advisory_lock</primary>
+ </indexterm>
+ <para>
+ <function>pg_try_advisory_lock</> as <function>pg_advisory_lock</>,
+ except the function will not wait until the lock is available. It will return
+ true if it is available (success) and false if it is not.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_try_advisory_lock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_try_advisory_lock_shared</> as
+ <function>pg_advisory_lock_shared</>, except the function will not wait
+ until the lock is available. It will return true if it is available
+ (success) and false if it is not.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_unlock</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock</> will release an exclude advisory lock. It
+ will return true if the lock is released. If no lock is available, it will
+ return false. In addition, an SQL warning will be raised by the backend.
+ </para>
+
+ <indexterm zone="functions-admin">
+ <primary>pg_advisory_unlock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock_shared</> 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</> as will release all advisory locks
+ held by the current session.
+ </para>
</sect1>
</chapter>
Index: src/sgml/mvcc.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v
retrieving revision 2.62
diff -u -p -r2.62 mvcc.sgml
--- src/sgml/mvcc.sgml 18 Sep 2006 12:11:36 -0000 2.62
+++ src/sgml/mvcc.sgml 19 Sep 2006 18:19:57 -0000
@@ -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. Internal
+ integrity 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,11 @@
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 +56,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 scoped
+ to a transaction.
</para>
</sect1>
@@ -859,6 +865,66 @@ UPDATE accounts SET balance = balance -
(e.g., while waiting for user input).
</para>
</sect2>
+
+ <sect2 id="advisory-locks">
+ <title>Advisory Locks</title>
+
+ <indexterm zone="advisory-locks">
+ <primary>advisory</primary>
+ </indexterm>
+
+ <para>
+ <productname>PostgreSQL</productname> provides a means for
+ creating locks that have an application defined meaning, called
+ advisory locks. Advisory locks are suitable for locking strategies
+ that are an awkward fit for the MVCC model. They have a lifetime
+ that is scoped to the end of the session or the lock is released,
+ whichever is sooner. Unlike standard locks, advisory locks do not
+ honor transaction semantics. For example, a lock acquired during a
+ transaction that is rolled back will still be held following the
+ rollback. The same lock can be acquired multiple times by its
+ owning process: for each lock there must be a corresponding unlock
+ for the lock to be fully released. Like all locks in
+ <productname>PostgreSQL</productname>, a complete list of advisory
+ locks held by the system can be listed in the system catalog
+ <structname>pg_locks</structname>.
+ </para>
+
+ <para>
+ Advisory locks are allocated out of a shared buffer pool whose size
+ is defined by the configuration variables max_connections and
+ max_locks_per_transaction. Care must be given not to exhaust this
+ memory or the server will not be able to grant any locks at all.
+ This imposes an aper limit on the amount of advisory locks
+ grantable by the server in the tens or 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 'flat file' data management systems.
+ While a table based flag could be used for the same purpose,
+ advisory locks are faster, avoid MVCC bloat, and are cleaned up
+ by the server at the end of the session.
+ Integer based keys are especially well suited for this type of lock
+ management. In certain cases using this method, especially in queries
+ involving explicit ordering and limit, care must be given to control
+ the amount of locks required because of the order in which the SQL
+ expressions are evaluated. For example:
+<screen>
+SELECT pg_advisory_lock(id, 0, 0) FROM foo WHERE id = 12345; -- ok
+SELECT pg_advisory_lock(id, 0, 0) FROM foo WHERE id > 12345 LIMIT 100; -- danger!
+SELECT pg_advisory_lock(q.id, 0, 0) FROM
+(
+ select * foo WHERE id > 12345 LIMIT 100;
+) q; -- ok
+</screen>
+ In the above queries, the second form is dangerous because the limit
+ expression is not guaranteed to evaluate before the locking function.
+ In this case, from the point of view of the application, the locks
+ would be dangling, although still viewable in pg_locks.
+ </sect2>
+
</sect1>
<sect1 id="applevel-consistency">
"Merlin Moncure" <mmoncure@gmail.com> writes:
ok, here is the promised docs for the advisory locks.
Applied with light editorialization.
some quick notes here: this is my first non trivial patch (albeit only
documentation) and i am a complete docbook novice.
Not bad for a first try --- I fixed a few things, but I wish all docs
submissions were this clean ;-)
regards, tom lane