Row-level lock modes

In older versions, as in PostgreSQL 9.3, there are only two locking modes, which are FOR UPDATE and FOR SHAREFOR UPDATE is used to acquire an exclusive lock on the row and does not allow other transactions to update or delete it; FOR SHARE is less restrictive, allows other transactions to lock the ROW in FOR SHARE mode, and still does not it allow other transactions to delete or update the row. FOR SHARE is used to handle a nonrepeatable read scenario in a READ COMMITTED transaction isolation level. For example, one could lock the row's FOR SHARE and this will guarantee that the value will not change until the transaction is committed.

FOR SHARE does not handle the lost update problem, since FOR SHARE allows other transactions to lock the row in the same mode. To handle a lost update problem, FOR UPDATE can be used. 

Lost updates happen when two transactions try to update the same row concurrently. See the deadlock section, which presents a lost update scenario.

PostgreSQL also provides the FOR NO KEY UPDATE, which is similar to the FOR UPDATE but the lock is weaker, and FOR KEY SHARE, which is again a weaker form of FOR SHARE. The row-level locking mode conflicts are given in the following table:

To test row-level locking, let's truncate the test_tx_level and populate a new record, as follows:

postgres=# truncate test_tx_level ;
TRUNCATE TABLE
postgres=# insert into test_tx_level Values(1), (2);
INSERT 0 2

To test for an updated row-level lock: 

Session 1

Session 2

T1

postgres=# BEGIN;
BEGIN
postgres=# SELECT * FROM test_tx_level WHERE val = 1 FOR update;
val
-----
1
(1 row)

T2

postgres=# BEGIN; 
BEGIN
postgres=# update test_tx_level SET val =2 WHERE val =1;

Session 2 is waiting for session 1, since it has acquired a FOR UPDATE lock.

postgres=# SELECT * FROM lock_info ;
-[ RECORD 1 ]-----+------------------------------------------------------
locked_pid | 3368
locked_user | postgres
locked_statement | update test_tx_level SET val =2 WHERE val =1;
state | active
locking_statement | SELECT * FROM test_tx_level WHERE val = 1 FOR update;
state | idle in transaction
locking_duration | 00:04:04.631108
locking_pid | 3380
locking_user | postgres
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset