58

我已经阅读了Java Persistence 2.0 中的 Locking and Concurrency文章,并运行了示例应用程序。但我仍然无法意识到 和 之间的PESSIMISTIC_READ区别PESSIMISTIC_WRITE。我尝试修改代码,代码使用PESSIMISTIC_READPESSIMISTIC_WRITE将具有与 SQL 调用相同的结果for update

4

5 回答 5

54

区别在于锁定机制。

PESSIMISTIC_READlock 意味着当你有这样的锁时,脏读和不可重复读是不可能的。如果要更改数据,则需要获取PESSIMISTIC_WRITE

PESSIMISTIC_WRITElock 保证除了脏读和不可重复读之外,您可以在不获取额外锁的情况下更新数据(并且deadlocks在等待独占锁时可能)。

╔══════════════════════╦══════════════════════════╦══════════════════════════╗
║     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       ║
╚══════════════════════╩══════════════════════════╩══════════════════════════╝

资源:

JPA 2.1

于 2013-12-11T23:51:41.120 回答
29

一个是读锁,另一个是写锁,或者分别在读取或更新期间。

自由贸易协定:

  • PESSIMISTIC_READ。实体管理器在事务读取实体后立即锁定它。锁定一直保持到事务完成。当您要使用可重复读取语义查询数据时,使用此锁定模式。换句话说,您要确保在连续读取之间不会更新数据。这种锁定模式不会阻止其他事务读取数据。

    PESSIMISTIC_WRITE。一旦事务更新实体,实体管理器就会锁定实体。此锁定模式强制尝试更新实体数据的事务之间进行序列化。当并发更新事务之间更新失败的可能性很高时,通常使用这种锁定模式。

于 2009-11-01T13:22:32.167 回答
25

这可能是技术含量最低的答案,所以如果我弄错了语义,我们深表歉意。但是我对之前答案中语言的复杂性感到沮丧,所以我决定发布一个简单的答案:

  • PESSIMISTIC_READ:您在事务开始时获得对记录的锁定,用于只读目的。基本上,您是在说“我不希望任何人在我阅读此记录时更新它,但我不介意其他人也阅读它”。这意味着尝试 PESSIMISTIC_READ 的人也会成功,但尝试 PESSIMISTIC_WRITE 的人会失败

  • PESSIMISTIC_WRITE:您在事务开始时获得对记录的锁定,用于写入。您所说的是“我将更新此记录,因此在我完成之前没有人可以读取或写入它”。这意味着那些尝试 PESSIMISTIC_READ 或 PESSIMISTIC_WRITE 的人都将失败

PESSIMISTIC 部分是指您在事务开始时获得锁的事实,即在对记录进行任何更改之前,而不是在事务结束时,当您即将提交对记录的更改时。

于 2020-09-07T16:38:09.747 回答
23

PESSIMISTIC_READ获取关联表行记录的共享(读取)锁,而获取PESSIMISTIC_WRITE排他(写入)锁。

共享锁阻止任何其他并发的独占锁请求,但它允许其他共享锁请求继续进行。

排他锁会阻止共享锁和排他锁请求。

值得一提的是,对于Hibernate,如果数据库不支持共享锁(例如Oracle),那么共享锁请求(例如,PESSIMISTIC_READ)将简单地获取排他锁请求(例如,PESSIMISTIC_WRITE)。

于 2016-10-25T05:42:37.473 回答
5

该规范允许 JPA 实现为每个使用不同类型的数据库锁。大多数数据库只有一种声明性锁,因此在大多数实现中,两者是相同的(没有区别)。

于 2012-12-19T15:11:32.397 回答