aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-05-04 17:43:27 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-05-04 17:44:31 -0400
commit71b9549d053b2f0a9e76e829c917385841f84bee (patch)
treebbe5a2fa115e15a0b9ecb21bc11e76e335d2eac4 /doc/src
parent1715ff112809bca5218ddb6eccfda2c20dc420b5 (diff)
downloadpostgresql-71b9549d053b2f0a9e76e829c917385841f84bee.tar.gz
postgresql-71b9549d053b2f0a9e76e829c917385841f84bee.zip
Overdue code review for transaction-level advisory locks patch.
Commit 62c7bd31c8878dd45c9b9b2429ab7a12103f3590 had assorted problems, most visibly that it broke PREPARE TRANSACTION in the presence of session-level advisory locks (which should be ignored by PREPARE), as per a recent complaint from Stephen Rees. More abstractly, the patch made the LockMethodData.transactional flag not merely useless but outright dangerous, because in point of fact that flag no longer tells you anything at all about whether a lock is held transactionally. This fix therefore removes that flag altogether. We now rely entirely on the convention already in use in lock.c that transactional lock holds must be owned by some ResourceOwner, while session holds are never so owned. Setting the locallock struct's owner link to NULL thus denotes a session hold, and there is no redundant marker for that. PREPARE TRANSACTION now works again when there are session-level advisory locks, and it is also able to transfer transactional advisory locks to the prepared transaction, but for implementation reasons it throws an error if we hold both types of lock on a single lockable object. Perhaps it will be worth improving that someday. Assorted other minor cleanup and documentation editing, as well. Back-patch to 9.1, except that in the 9.1 branch I did not remove the LockMethodData.transactional flag for fear of causing an ABI break for any external code that might be examining those structs.
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/func.sgml67
-rw-r--r--doc/src/sgml/mvcc.sgml76
2 files changed, 78 insertions, 65 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 82bac4d6641..61e19b337c1 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -15382,7 +15382,7 @@ SELECT (pg_stat_file('filename')).modification;
<literal><function>pg_advisory_xact_lock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal>
</entry>
<entry><type>void</type></entry>
- <entry>Obtain shared advisory lock for the current transaction</entry>
+ <entry>Obtain shared transaction level advisory lock</entry>
</row>
<row>
<entry>
@@ -15451,11 +15451,10 @@ SELECT (pg_stat_file('filename')).modification;
<function>pg_advisory_lock</> locks an application-defined resource,
which can 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).
- The key type is specified in <literal>pg_locks.objid</>. If
- another session already holds a lock on the same resource, the
- function will wait until the resource becomes available. The lock
+ If another session already holds a lock on the same resource identifier,
+ this 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
+ is locked three times it must then be unlocked three times to be
released for other sessions' use.
</para>
@@ -15490,6 +15489,35 @@ SELECT (pg_stat_file('filename')).modification;
</para>
<indexterm>
+ <primary>pg_advisory_unlock</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock</> will release a previously-acquired
+ exclusive session level advisory lock. It
+ returns <literal>true</> if the lock is successfully released.
+ If the lock was not held, it will return <literal>false</>,
+ and in addition, an SQL warning will be reported by the server.
+ </para>
+
+ <indexterm>
+ <primary>pg_advisory_unlock_shared</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock_shared</> works the same as
+ <function>pg_advisory_unlock</>,
+ except it releases a shared session level advisory lock.
+ </para>
+
+ <indexterm>
+ <primary>pg_advisory_unlock_all</primary>
+ </indexterm>
+ <para>
+ <function>pg_advisory_unlock_all</> will release all session level advisory
+ locks held by the current session. (This function is implicitly invoked
+ at session end, even if the client disconnects ungracefully.)
+ </para>
+
+ <indexterm>
<primary>pg_advisory_xact_lock</primary>
</indexterm>
<para>
@@ -15527,35 +15555,6 @@ SELECT (pg_stat_file('filename')).modification;
cannot be released explicitly.
</para>
- <indexterm>
- <primary>pg_advisory_unlock</primary>
- </indexterm>
- <para>
- <function>pg_advisory_unlock</> will release a previously-acquired
- exclusive session level advisory lock. It
- returns <literal>true</> if the lock is successfully released.
- If the lock was not held, it will return <literal>false</>,
- and in addition, an SQL warning will be raised by the server.
- </para>
-
- <indexterm>
- <primary>pg_advisory_unlock_shared</primary>
- </indexterm>
- <para>
- <function>pg_advisory_unlock_shared</> works the same as
- <function>pg_advisory_unlock</>,
- except it releases a shared session level advisory lock.
- </para>
-
- <indexterm>
- <primary>pg_advisory_unlock_all</primary>
- </indexterm>
- <para>
- <function>pg_advisory_unlock_all</> will release all session level advisory
- locks held by the current session. (This function is implicitly invoked
- at session end, even if the client disconnects ungracefully.)
- </para>
-
</sect2>
</sect1>
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index 85221ae4544..8f8858294dc 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -1208,6 +1208,10 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
<title>Advisory Locks</title>
<indexterm zone="advisory-locks">
+ <primary>advisory lock</primary>
+ </indexterm>
+
+ <indexterm zone="advisory-locks">
<primary>lock</primary>
<secondary>advisory</secondary>
</indexterm>
@@ -1218,35 +1222,51 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
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.</para>
+ that are an awkward fit for the MVCC model.
+ For example, 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 table bloat, and are automatically
+ cleaned up by the server at the end of the session.
+ </para>
<para>
- There are two different types of advisory locks in
- <productname>PostgreSQL</productname>: session level and transaction level.
- Once acquired, a session level advisory lock is held until explicitly
- released or the session ends. Unlike standard locks, session level
- advisory locks do not honor transaction semantics: a lock acquired during
- a transaction that is later rolled back will still be held following the
- rollback, and likewise an unlock is effective even if the calling
- transaction fails later. The same session level 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.) Transaction level locks on
- the other hand behave more like regular locks; they are automatically
- released at the end of the transaction, and can not be explicitly unlocked.
- Session and transaction level locks share the same lock space, which means
- that a transaction level lock will prevent another session from obtaining
- a session level lock on that same resource and vice versa.
- Like all locks in <productname>PostgreSQL</productname>, a complete list of
- advisory locks currently held by any session can be found in the
- <link linkend="view-pg-locks"><structname>pg_locks</structname></link>
- system view.
+ There are two ways to acquire an advisory lock in
+ <productname>PostgreSQL</productname>: at session level or at
+ transaction level.
+ Once acquired at session level, an advisory lock is held until
+ explicitly released or the session ends. Unlike standard lock requests,
+ session-level advisory lock requests do not honor transaction semantics:
+ a lock acquired during a transaction that is later rolled back will still
+ be held following the rollback, and likewise an unlock is effective even
+ if the calling transaction fails later. A lock can be acquired multiple
+ times by its owning process; for each completed lock request there must
+ be a corresponding unlock request before the lock is actually released.
+ Transaction-level lock requests, on the other hand, behave more like
+ regular lock requests: they are automatically released at the end of the
+ transaction, and there is no explicit unlock operation. This behavior
+ is often more convenient than the session-level behavior for short-term
+ usage of an advisory lock.
+ Session-level and transaction-level lock requests for the same advisory
+ lock identifier will block each other in the expected way.
+ If a session already holds a given advisory lock, additional requests by
+ it will always succeed, even if other sessions are awaiting the lock; this
+ statement is true regardless of whether the existing lock hold and new
+ request are at session level or transaction level.
</para>
<para>
- Advisory locks are allocated out of a shared memory pool whose size
- is defined by the configuration variables
+ Like all locks in
+ <productname>PostgreSQL</productname>, a complete list of advisory locks
+ currently held by any session can be found in the <link
+ linkend="view-pg-locks"><structname>pg_locks</structname></link> system
+ view.
+ </para>
+
+ <para>
+ Both advisory locks and regular locks are stored in 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
@@ -1257,13 +1277,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
</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 can be automatically
- cleaned up by the server at the end of the session.
- In certain cases using this advisory locking method, especially in queries
+ In certain cases using advisory locking methods, 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: