我已经阅读了文章Java Persistence 2.0中的锁定和并发,并运行了示例应用程序。但我仍然无法理解PESSIMISTIC_READ
和PESSIMISTIC_WRITE
之间的区别。 我尝试修改代码,并且在使用 PESSIMISTIC_READ
和 PESSIMISTIC_WRITE
的代码位置将产生相同的结果,即SQL将使用 for update
进行调用。
我已经阅读了文章Java Persistence 2.0中的锁定和并发,并运行了示例应用程序。但我仍然无法理解PESSIMISTIC_READ
和PESSIMISTIC_WRITE
之间的区别。 我尝试修改代码,并且在使用 PESSIMISTIC_READ
和 PESSIMISTIC_WRITE
的代码位置将产生相同的结果,即SQL将使用 for update
进行调用。
这可能是最不技术性的答案,如果我在语义上有错误,请谅解。但是,我对先前答案中语言的复杂性感到沮丧,所以我决定发布一个简单的答案:
PESSIMISTIC_READ:你在事务开始时获取记录的锁,仅为了读取目的。基本上你是在说:“当我阅读它时,我不希望任何人更新该记录,但我不介意其他人也读取它”。这意味着尝试 PESSIMISTIC_READ 的人也会成功,但尝试 PESSIMISTIC_WRITE 的人将失败。
PESSIMISTIC_WRITE:你在事务开始时获取记录的锁,用于写入操作。你的意思是:“我将更新此记录,因此在我完成之前,没有人可以读取或写入它。” 这意味着尝试 PESSIMISTIC_READ 或 PESSIMISTIC_WRITE 的人都将失败。
“PESSIMISTIC” 部分指的是您在事务开始之前(即在对记录进行任何更改之前)获取锁,而不是在事务结束时(当您即将提交对记录的更改)。
PESSIMISTIC_READ
锁表示当你拥有这样的锁时,不可能进行脏读和不可重复读。如果数据需要更改,则需要获取 PESSIMISTIC_WRITE
锁。
PESSIMISTIC_WRITE
锁保证了除了脏读和不可重复读之外,您可以更新数据而无需获取其他锁(并可能在等待独占锁时发生死锁)。╔══════════════════════╦══════════════════════════╦══════════════════════════╗
║ 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:
其中一个是读锁,另一个是写锁,分别用于读取或更新期间。
FTA:
PESSIMISTIC_READ。实体管理器在事务读取实体时立即锁定该实体。锁将保持到事务完成为止。当您想使用可重复读语义查询数据时使用此锁模式。换句话说,您希望确保数据在连续读取之间不被更新。此锁模式不会阻塞其他事务读取数据。
PESSIMISTIC_WRITE。当事务更新实体时,实体管理器会立即锁定该实体。此锁模式在试图更新实体数据的并发事务之间强制进行序列化。当存在许多并发更新事务中的更新失败的高概率时,通常使用此锁模式。
PESSIMISTIC_READ
会在相关的表行记录上获取共享(读)锁,而 PESSIMISTIC_WRITE
则会获取排他(写)锁。
共享锁会阻塞其他并发的排它锁请求,但是允许其他共享锁请求继续。
排它锁会阻塞同时具有共享锁和排它锁请求。
值得一提的是,对于 Hibernate 来说,如果数据库不支持共享锁(比如 Oracle),那么共享锁请求(如 PESSIMISTIC_READ
)将简单地获取一个排他锁请求(如 PESSIMISTIC_WRITE
)。