diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index 3fbe0c9b68..a0d6867de0 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -1106,30 +1106,108 @@ ERROR: could not serialize access due to read/write dependencies among transact
In addition to table-level locks, there are row-level locks, which
- can be exclusive or shared locks. An exclusive row-level lock on a
- specific row is automatically acquired when the row is updated or
- deleted. The lock is held until the transaction commits or rolls
- back, just like table-level locks. Row-level locks do
- not affect data querying; they block only writers to the same
- row.
+ are listed as below with the contexts in which they are used
+ automatically by PostgreSQL. See
+ for a complete table of
+ row-level lock conflicts. Note that a transaction can hold
+ conflicting locks on the same row, even in different subtransactions;
+ but other than that, two transactions can never hold conflicting locks
+ on the same row. Row-level locks do not affect data querying; they
+ block only writers and lockers to the same row.
-
- To acquire an exclusive row-level lock on a row without actually
- modifying the row, select the row with SELECT FOR
- UPDATE. Note that once the row-level lock is acquired,
- the transaction can update the row multiple times without
- fear of conflicts.
-
+
+ Row-level Lock Modes
+
+
+ FOR UPDATE
+
+
+
+ FOR UPDATE causes the rows retrieved by the
+ SELECT statement to be locked as though for
+ update. This prevents them from being locked, modified or deleted by
+ other transactions until the current transaction ends. That is,
+ other transactions that attempt UPDATE,
+ DELETE,
+ SELECT FOR UPDATE,
+ SELECT FOR NO KEY UPDATE,
+ SELECT FOR SHARE or
+ SELECT FOR KEY SHARE
+ of these rows will be blocked until the current transaction ends;
+ conversely, SELECT FOR UPDATE will wait for a
+ concurrent transaction that has run any of those commands on the
+ same row,
+ and will then lock and return the updated row (or no row, if the
+ row was deleted). Within a REPEATABLE READ> or
+ SERIALIZABLE> transaction,
+ however, an error will be thrown if a row to be locked has changed
+ since the transaction started. For further discussion see
+ .
+
+
+ The FOR UPDATE> lock mode
+ is also acquired by any DELETE> on a row, and also by an
+ UPDATE> that modifies the values on certain columns. Currently,
+ the set of columns considered for the UPDATE> case are those that
+ have a unique index on them that can be used in a foreign key (so partial
+ indexes and expressional indexes are not considered), but this may change
+ in the future.
+
+
+
-
- To acquire a shared row-level lock on a row, select the row with
- SELECT FOR SHARE. A shared lock does not prevent
- other transactions from acquiring the same shared lock. However,
- no transaction is allowed to update, delete, or exclusively lock a
- row on which any other transaction holds a shared lock. Any attempt
- to do so will block until the shared lock(s) have been released.
-
+
+
+ FOR NO KEY UPDATE
+
+
+
+ Behaves similarly to FOR UPDATE>, except that the lock
+ acquired is weaker: this lock will not block
+ SELECT FOR KEY SHARE> commands that attempt to acquire
+ a lock on the same rows. This lock mode is also acquired by any
+ UPDATE> that does not acquire a FOR UPDATE> lock.
+
+
+
+
+
+
+ FOR SHARE
+
+
+
+ Behaves similarly to FOR NO KEY UPDATE>, except that it
+ acquires a shared lock rather than exclusive lock on each retrieved
+ row. A shared lock blocks other transactions from performing
+ UPDATE, DELETE,
+ SELECT FOR UPDATE or
+ SELECT FOR NO KEY UPDATE> on these rows, but it does not
+ prevent them from performing SELECT FOR SHARE or
+ SELECT FOR KEY SHARE.
+
+
+
+
+
+
+ FOR KEY SHARE
+
+
+
+ Behaves similarly to FOR SHARE, except that the
+ lock is weaker: SELECT FOR UPDATE> is blocked, but not
+ SELECT FOR NO KEY UPDATE>. A key-shared lock blocks
+ other transactions from performing DELETE or
+ any UPDATE that changes the key values, but not
+ other UPDATE>, and neither does it prevent
+ SELECT FOR NO KEY UPDATE>, SELECT FOR SHARE>,
+ or SELECT FOR KEY SHARE>.
+
+
+
+
PostgreSQL doesn't remember any
@@ -1140,6 +1218,61 @@ ERROR: could not serialize access due to read/write dependencies among transact
will result in disk writes.
+
+ Conflicting Row-level Locks
+
+
+
+
+
+
+ Requested Lock Mode
+ Current Lock Mode
+
+
+ FOR KEY SHARE
+ FOR SHARE
+ FOR NO KEY UPDATE
+ FOR UPDATE
+
+
+
+
+ FOR KEY SHARE
+
+
+
+ X
+
+
+ FOR SHARE
+
+
+ X
+ X
+
+
+ FOR NO KEY UPDATE
+
+ X
+ X
+ X
+
+
+ FOR UPDATE
+ X
+ X
+ X
+ X
+
+
+
+
+
+
+
+ Page-level Locks
+
In addition to table and row locks, page-level share/exclusive locks are
used to control read/write access to table pages in the shared buffer
diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml
index 940d1aa5c0..4948a6d815 100644
--- a/doc/src/sgml/ref/select.sgml
+++ b/doc/src/sgml/ref/select.sgml
@@ -1298,64 +1298,8 @@ KEY SHARE
- FOR UPDATE causes the rows retrieved by the
- SELECT statement to be locked as though for
- update. This prevents them from being modified or deleted by
- other transactions until the current transaction ends. That is,
- other transactions that attempt UPDATE,
- DELETE,
- SELECT FOR UPDATE,
- SELECT FOR NO KEY UPDATE,
- SELECT FOR SHARE or
- SELECT FOR KEY SHARE
- of these rows will be blocked until the current transaction ends.
- The FOR UPDATE> lock mode
- is also acquired by any DELETE> on a row, and also by an
- UPDATE> that modifies the values on certain columns. Currently,
- the set of columns considered for the UPDATE> case are those that
- have a unique index on them that can be used in a foreign key (so partial
- indexes and expressional indexes are not considered), but this may change
- in the future.
- Also, if an UPDATE, DELETE,
- or SELECT FOR UPDATE from another transaction
- has already locked a selected row or rows, SELECT FOR
- UPDATE will wait for the other transaction to complete,
- and will then lock and return the updated row (or no row, if the
- row was deleted). Within a REPEATABLE READ> or SERIALIZABLE> transaction,
- however, an error will be thrown if a row to be locked has changed
- since the transaction started. For further discussion see .
-
-
-
- FOR NO KEY UPDATE> behaves similarly, except that the lock
- acquired is weaker: this lock will not block
- SELECT FOR KEY SHARE> commands that attempt to acquire
- a lock on the same rows. This lock mode is also acquired by any
- UPDATE> that does not acquire a FOR UPDATE> lock.
-
-
-
- FOR SHARE behaves similarly, except that it
- acquires a shared rather than exclusive lock on each retrieved
- row. A shared lock blocks other transactions from performing
- UPDATE, DELETE, SELECT
- FOR UPDATE or SELECT FOR NO KEY UPDATE>
- on these rows, but it does not prevent them
- from performing SELECT FOR SHARE or
- SELECT FOR KEY SHARE.
-
-
-
- FOR KEY SHARE> behaves similarly to FOR SHARE,
- except that the lock
- is weaker: SELECT FOR UPDATE> is blocked, but
- not SELECT FOR NO KEY UPDATE>. A key-shared
- lock blocks other transactions from performing DELETE
- or any UPDATE that changes the key values, but not
- other UPDATE>, and neither does it prevent
- SELECT FOR NO KEY UPDATE>, SELECT FOR SHARE>, or
- SELECT FOR KEY SHARE>.
+ For more information on each row-level lock mode, refer to
+ .