From 974b360cc8bfdade607154c94d0a78f5cf466e0a Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Fri, 10 Oct 2014 22:10:10 +0900 Subject: [PATCH] Refactor documentation of row-level locking All the details about each row-level lock mode was referenced in details in the page dedicated to SELECT query, what seems rather incorrect because there is a section in MVCC section describing in details all the locks that can be used in the system. Note that this portion has not been updated for the implementation of FOR KEY SHARE and FOR NO KEY UPDATE while it should have been the case, making the information provided to user inconsistent and misleading. This patch refactors the whole, adding a link in SELECT to redirect the user to the page describing all the explicit locks of the system. --- doc/src/sgml/mvcc.sgml | 172 +++++++++++++++++++++++++++++++++++++------ doc/src/sgml/ref/select.sgml | 60 +-------------- 2 files changed, 152 insertions(+), 80 deletions(-) diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index cd55be8..478279d 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -1106,30 +1106,107 @@ 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. The main + differences between one lock mode and another is the set of lock modes + with each conflicts (see ). + Two transactions cannot hold locks of conflicting modes on the same rows + of the same table at the same time. Also, a transaction never conflicts + with itself. Row-level locks do not affect data querying; they block only + writers 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 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 + . + + + - - 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 @@ -1139,11 +1216,62 @@ ERROR: could not serialize access due to read/write dependencies among transact UPDATE modifies selected rows to mark them locked, and so will result in disk writes. + + + Conflicting Row-level Locks + + + + + + + Requested Lock Mode + Current Lock Mode + + + FOR UPDATE + FOR NO KEY UPDATE + FOR SHARE + FOR KEY SHARE + + + + + FOR UPDATE + X + X + X + X + + + FOR NO KEY UPDATE + X + X + X + + + + FOR SHARE + X + X + + + + + FOR KEY SHARE + 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 473939a..3e5a2f5 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 + . -- 2.1.2