From 955b4ba7f6948359efcef1c47035d382f937e9f3 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Thu, 13 Nov 2014 14:45:58 -0300 Subject: [PATCH] Tweak row-level locking documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the meat of locking levels to mvcc.sgml, leaving only a link to it in the SELECT reference page. Michael Paquier, with some tweaks by Álvaro --- doc/src/sgml/mvcc.sgml | 175 ++++++++++++++++++++++++++++++----- doc/src/sgml/ref/select.sgml | 60 +----------- 2 files changed, 156 insertions(+), 79 deletions(-) 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 + .