From: Tom Lane Date: Fri, 1 Dec 2006 20:50:06 +0000 (+0000) Subject: Document the recently-understood hazard that a rollback can release row-level X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=baeb6e2aba172106093ed98aecc3b8692c7d9f16;p=users%2Fbernd%2Fpostgres.git 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... --- diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml index 41405466a9..96f533eada 100644 --- a/doc/src/sgml/ref/select.sgml +++ b/doc/src/sgml/ref/select.sgml @@ -825,6 +825,41 @@ FOR UPDATE [ OF table_name [, ...] effectively executes after LIMIT, however, and so that is the recommended place to write it. + + + + Avoid locking a row and then modifying it within a later savepoint or + PL/pgSQL exception block. A subsequent + rollback would cause the lock to be lost. For example, + +BEGIN; +SELECT * FROM mytable WHERE key = 1 FOR UPDATE; +SAVEPOINT s; +UPDATE mytable SET ... WHERE key = 1; +ROLLBACK TO s; + + After the 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 PostgreSQL. + + + + + + It is possible for a SELECT command using both + LIMIT and FOR UPDATE + clauses to return fewer rows than specified by LIMIT. + This is because LIMIT selects a number of rows, + but might then block requesting a FOR UPDATE lock. + Once the SELECT unblocks, the query qualification might not + be met and the row not be returned by SELECT. + + @@ -874,7 +909,7 @@ SELECT kind, sum(len) AS total FROM films GROUP BY kind; SELECT kind, sum(len) AS total FROM films GROUP BY kind - HAVING sum(len) < interval '5 hours'; + HAVING sum(len) < interval '5 hours'; kind | total ----------+-------