Document the recently-understood hazard that a rollback can release row-level

locks that logically should not be released, because when a subtransaction
overwrites XMAX all knowledge of the previous lock state is lost.  It seems
unlikely that we will be able to fix this before 8.3...
This commit is contained in:
Tom Lane 2006-12-01 20:50:06 +00:00
parent 8462c4a5b4
commit 1eaf9ef62a

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.80.4.2 2005/04/22 15:53:27 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.80.4.3 2006/12/01 20:50:06 tgl Exp $
PostgreSQL documentation
-->
@ -818,6 +818,38 @@ FOR UPDATE [ OF <replaceable class="parameter">table_name</replaceable> [, ...]
rows; for example it can't be used with aggregation.
</para>
<para>
<literal>FOR UPDATE</literal> may appear before
<literal>LIMIT</literal> for compatibility with
<productname>PostgreSQL</productname> versions before 7.3. It
effectively executes after <literal>LIMIT</literal>, however, and
so that is the recommended place to write it.
</para>
<caution>
<para>
Avoid locking a row and then modifying it within a later savepoint or
<application>PL/pgSQL</application> exception block. A subsequent
rollback would cause the lock to be lost. For example,
<programlisting>
BEGIN;
SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE mytable SET ... WHERE key = 1;
ROLLBACK TO s;
</programlisting>
After the <command>ROLLBACK</>, the row is effectively unlocked, rather
than returned to its pre-savepoint state of being locked but not modified.
This hazard occurs if a row locked in the current transaction is updated
or deleted: the former lock state is forgotten. If the transaction is then
rolled back to a state between the original locking command and the
subsequent change, the row will appear not to be locked at all. This is
an implementation deficiency which will be addressed in a future release
of <productname>PostgreSQL</productname>.
</para>
</caution>
<caution>
<para>
It is possible for a <command>SELECT</> command using both
<literal>LIMIT</literal> and <literal>FOR UPDATE</literal>
@ -827,14 +859,7 @@ FOR UPDATE [ OF <replaceable class="parameter">table_name</replaceable> [, ...]
Once the <literal>SELECT</> unblocks, the query qualification might not
be met and the row not be returned by <literal>SELECT</>.
</para>
<para>
<literal>FOR UPDATE</literal> may appear before
<literal>LIMIT</literal> for compatibility with
<productname>PostgreSQL</productname> versions before 7.3. It
effectively executes after <literal>LIMIT</literal>, however, and
so that is the recommended place to write it.
</para>
</caution>
</refsect2>
</refsect1>