73

I have read the article Locking and Concurrency in Java Persistence 2.0, and run the sample application. But I still can't realize the difference between PESSIMISTIC_READ and PESSIMISTIC_WRITE. I tried to modify the code, and where the code using PESSIMISTIC_READ and PESSIMISTIC_WRITE will have the same result that the SQL will invoked with for update.

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
paka
  • 739
  • 1
  • 5
  • 3

5 Answers5

77

This is probably going to be the least technical answer, so apologies if I get the semantics wrong. But I was frustrated with the complexity of the language in the previous answers, so I decided to post a simple answer:

  • PESSIMISTIC_READ: you obtain a lock on the record at the start of the transaction, for the purpose of reading only. Basically you're saying "I don't want anyone updating this record while I'm reading it, but I don't mind others reading it as well". That means people also attempting a PESSIMISTIC_READ will succeed, but those attempting a PESSIMISTIC_WRITE will fail

  • PESSIMISTIC_WRITE: you obtain a lock on the record at the start of the transaction, for the purpose of writing. What you're saying is "I'm going to be updating this record, so no one can read or write to it until I'm done". That means both those attempting a PESSIMISTIC_READ or PESSIMISTIC_WRITE will fail

the PESSIMISTIC part refers to the fact that you get the lock at the start of the transaction i.e. before making any changes to the record, rather than at the end of the transaction, when you are about to commit the changes to the record.

taleb
  • 996
  • 7
  • 6
  • Hi @taleb I want to confirm something. I just do some testing with this PESSIMISTIC_READ and PESSIMISTIC_WRITE. In the answer above you mention fail transaction for some cases, but when I try to reproduce the case the transaction will wait instead of failing. So it actually is "will wait" instead of "will fail" or I misunderstood something? – Irvan Aug 27 '22 at 08:00
60

The difference lies in locking mechanism.

PESSIMISTIC_READ lock means that dirty reads and non-repeatable reads are impossible when you have such a lock. If data should be changed it's required to obtain PESSIMISTIC_WRITE lock

PESSIMISTIC_WRITE lock guarantees that besides dirty and non-repeatable reads are impossible you can update data without obtaining additional locks(and possible deadlocks while waiting for exclusive lock).

╔══════════════════════╦══════════════════════════╦══════════════════════════╗
║     LockModeType     ║     PESSIMISTIC_READ     ║    PESSIMISTIC_WRITE     ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣ 
║         type         ║       SHARED LOCK        ║      EXCLUSIVE LOCK      ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣   
║  isReadOnly without  ║                          ║                          ║
║   additional locks   ║            YES           ║            NO            ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣
║      dirty reads     ║            NO            ║            NO            ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣
║ non-repeatable reads ║            NO            ║            NO            ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣
║ how to update data   ║ obtain PESSIMISTIC_WRITE ║         ALLOWED          ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣
║                      ║       no one holds       ║      no one holds        ║
║ how to obtain lock   ║     PESSIMISTIC_WRITE    ║   PESSIMISTIC_READ   or  ║
║                      ║                          ║   PESSIMISTIC_WRITE      ║
╠══════════════════════╬══════════════════════════╬══════════════════════════╣
║                      ║                          ║   when there is a high   ║
║                      ║  you want to ensure no   ║ likelihood of deadlock or║
║      when to use     ║ dirty or non-repeatable  ║   update failure among   ║ 
║                      ║   reads are possible     ║    concurrent updating   ║
║                      ║                          ║       transactions       ║
╚══════════════════════╩══════════════════════════╩══════════════════════════╝

Resources:

JPA 2.1

Sergii Shevchyk
  • 38,716
  • 12
  • 50
  • 61
31

One is a read lock and the other is a write lock, or during a read or an update, respectively.

FTA:

  • PESSIMISTIC_READ. The entity manager locks the entity as soon as a transaction reads it. The lock is held until the transaction completes. This lock mode is used when you want to query data using repeatable-read semantics. In other words, you want to ensure that the data is not updated between successive reads. This lock mode does not block other transactions from reading the data.

    PESSIMISTIC_WRITE. The entity manager locks the entity as soon as a transaction updates it. This lock mode forces serialization among transactions attempting to update the entity data. This lock mode is often used when there is a high likelihood of update failure among concurrent updating transactions.

Joseph
  • 25,330
  • 8
  • 76
  • 125
  • 2
    thanks, i saw the description, but it still confuse me. When i using PESSIMISTIC_READ and PESSIMISTIC_WRITE, it always get the same result in "show sql" and running result. – paka Nov 01 '09 at 14:37
  • Nice explanation!. Could you please add some sample code to demonstrate ? – Velu Nov 27 '13 at 07:51
  • @paka: the JPA spec says: "It is permissible for an implementation to use LockModeType.PESSIMISTIC_WRITE where LockModeType.PESSIMISTIC_READ was requested, but not vice versa." see [this answer](http://stackoverflow.com/a/33081311/3994580) for details – DaniEll Nov 11 '16 at 08:36
  • @Joseph, Does PESSIMISTIC_READ force serialization among transactions attempting to read the entity data ? – Mahmoud Saleh Oct 04 '22 at 05:53
29

The PESSIMISTIC_READ acquires a shared (read) lock on the associated table row record, while the PESSIMISTIC_WRITE acquires an exclusive (write) lock.

The shared lock blocks any other concurrent exclusive lock requests, but it allows other shared lock requests to proceed.

The exclusive lock blocks both shared and exclusive lock requests.

What's worth mentioning is that, for Hibernate, if the database does not support shared locks (e.g. Oracle), then a shared lock request (e.g., PESSIMISTIC_READ) will simply acquire an exclusive lock request (e.g., PESSIMISTIC_WRITE).

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • Does PESSIMISTIC_READ force serialization among transactions attempting to read the entity data ? – Mahmoud Saleh Oct 04 '22 at 05:54
  • It depends on the underlying DB. For instance, on Oracle or PostgreSQL, such locks don't acquire predicate locks, so you won't get Serializability for ranges., only for individual records. – Vlad Mihalcea Oct 04 '22 at 06:28
5

The Spec allows for the JPA implementation to use a different type of database lock for each. Most databases only have one type of declarative lock, so in most implementations the two are identical (there is no difference).

James
  • 17,965
  • 11
  • 91
  • 146