oracle LockModeType Jpa 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33062635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between LockModeType Jpa
提问by eatSleepCode
I am confused about the working of LockModeTypes in JPA:
我对 JPA 中 LockModeTypes 的工作感到困惑:
LockModeType.Optimistic
- it increments the version while committing.
- Question here is : If I have version column in my entity and if I don't specify this lock mode then also it works similarly then what is the use of it?
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- Here it increments the version column even though the entity is not updated.
- but what is the use of it if any other process updated the same row before this transaction is committed? this transaction is anyways going to fail. so what is the use of this
LockModeType
.
LockModeType.PESSIMISTIC_READ
- This lock mode issues a
select for update nowait
(if no hint timeout specified).. - so basically this means that no other transaction can update this row until this transaction is committed, then its basically a write lock, why its named a
Read
lock?
- This lock mode issues a
LockModeType.PESSIMISTIC_WRITE
- This lock mode also issues a
select for update nowait
(if no hint timeout specified). - Question here is what is the difference between this lock mode and
LockModeType.PESSIMISTIC_READ
as I see both fires same queries?
- This lock mode also issues a
LockModeType.PESSIMISTIC_FORCE_INCREMENT
- this does
select for update nowait
(if no hint timeout specified) and also increments the version number. - I totally didn't get the use of it.
- why a version increment is required if
for update no wait
is there?
- this does
LockModeType.Optimistic
- 它在提交时增加版本。
- 这里的问题是:如果我的实体中有 version 列,并且如果我没有指定此锁定模式,那么它的工作方式也类似,那么它有什么用?
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- 即使实体没有更新,它也会在这里增加版本列。
- 但是如果在提交此事务之前任何其他进程更新了同一行,它有什么用?这笔交易无论如何都会失败。那么这个有什么用呢
LockModeType
。
LockModeType.PESSIMISTIC_READ
- 此锁定模式发出一个
select for update nowait
(如果没有指定提示超时).. - 所以基本上这意味着在提交此事务之前没有其他事务可以更新该行,那么它基本上是一个写锁,为什么它命名为
Read
锁?
- 此锁定模式发出一个
LockModeType.PESSIMISTIC_WRITE
- 此锁定模式还会发出
select for update nowait
(如果未指定提示超时)。 - 这里的问题是这种锁定模式和
LockModeType.PESSIMISTIC_READ
我看到的两者都触发相同的查询有什么区别?
- 此锁定模式还会发出
LockModeType.PESSIMISTIC_FORCE_INCREMENT
- 这样做
select for update nowait
(如果没有指定提示超时)并且还会增加版本号。 - 我完全没有使用它。
- 如果
for update no wait
有,为什么需要版本增量?
- 这样做
回答by OndroMih
I would first differentiate between optimistic and pessimistic locks, because they are different in their underlying mechanism.
我首先要区分乐观锁和悲观锁,因为它们的底层机制不同。
Optimistic locking is fully controlled by JPA and only requires additional version column in DB tables. It is completely independent of underlying DB engine used to store relational data.
乐观锁完全由 JPA 控制,只需要在 DB 表中添加额外的版本列。它完全独立于用于存储关系数据的底层数据库引擎。
On the other hand, pessimistic locking uses locking mechanism provided by underlying database to lock existing records in tables. JPA needs to know how to trigger these locks and some databases do not support them or only partially.
另一方面,悲观锁定使用底层数据库提供的锁定机制来锁定表中的现有记录。JPA 需要知道如何触发这些锁,而某些数据库不支持或仅部分支持。
Now to the list of lock types:
现在到锁类型列表:
LockModeType.Optimistic
- If entities specify a version field, this is the default. For entities without a version column, using this type of lock isn't guaranteed to work on any JPA implementation. This mode is usually ignored as stated by ObjectDB. In my opinion it only exists so that you may compute lock mode dynamically and pass it further even if the lock would be OPTIMISTIC in the end. Not very probable usecase though, but it is always good API design to provide an option to reference even the default value.
Example:
LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- This is a rarely used option. But it could be reasonable, if you want to lock referencing this entity by another entity. In other words you want to lock working with an entity even if it is not modified, but other entities may be modified in relation to this entity.
- Example: We have entity Book and Shelf. It is possible to add Book to Shelf, but book does not have any reference to its shelf. It is reasonable to lock the action of moving a book to a shelf, so that a book does not end up in another shelf (due to another transaction) before end of this transaction. To lock this action, it is not sufficient to lock current book shelf entity, as the book does not have to be on a shelf yet. It also does not make sense to lock all target bookshelves, as they would be probably different in different transactions. The only thing that makes sense is to lock the book entity itself, even if in our case it does not get changed (it does not hold reference to its bookshelf).
LockModeType.PESSIMISTIC_READ
- this mode is similar to
LockModeType.PESSIMISTIC_WRITE
, but different in one thing: until write lock is in place on the same entity by some transaction, it should not block reading the entity. It also allows other transactions to lock usingLockModeType.PESSIMISTIC_READ
. The differences between WRITE and READ locks are well explained here (ObjectDB)and here (OpenJPA). If an entity is already locked by another transaction, any attempt to lock it will throw an exception. This behavior can be modified to waiting for some time for the lock to be released before throwing an exception and roll back the transaction. In order to do that, specify thejavax.persistence.lock.timeout
hint with the number of milliseconds to wait before throwing the exception. There are multiple ways to do this on multiple levels, as described in the Java EE tutorial.
- this mode is similar to
LockModeType.PESSIMISTIC_WRITE
- this is a stronger version of
LockModeType.PESSIMISTIC_READ
. WhenWRITE
lock is in place, JPA with the help of the database will prevent any other transaction to read the entity, not only to write as withREAD
lock. - The way how this is implemented ina JPA provider in cooperation with underlying DB is not prescribed. In your case with Oracle, I would say that Oracle does not provide something close to a
READ
lock.SELECT...FOR UPDATE
is really rather aWRITE
lock. It may be a bug in hibernate or just a decision that, instead of implementing custom "softer"READ
lock, the "harder"WRITE
lock is used instead. This mostly does not break consistency, but does not hold all rules withREAD
locks. You could run some simple tests withREAD
locks and long running transactions to find out if more transactions are able to acquireREAD
locks on the same entity. This should be possible, whereas not withWRITE
locks.
- this is a stronger version of
LockModeType.PESSIMISTIC_FORCE_INCREMENT
- this is another rarely used lock mode. However, it is an option where you need to combine
PESSIMISTIC
andOPTIMISTIC
mechanisms. Using plainPESSIMISTIC_WRITE
would fail in following scenario:- transaction A uses optimistic locking and reads entity E
- transaction B acquires WRITE lock on entity E
- transaction B commits and releases lock of E
- transaction A updates E and commits
- in step 4, if version column is not incremented by transaction B, nothing prevents A from overwriting changes of B. Lock mode
LockModeType.PESSIMISTIC_FORCE_INCREMENT
will force transaction B to update version number and causing transaction A to fail withOptimisticLockException
, even though B was using pessimistic locking.
- this is another rarely used lock mode. However, it is an option where you need to combine
LockModeType.NONE
- this is the default if entities don't provide a version field. It means that no locking is enabled conflicts will be resolved on best effort basis and will not be detected. This is the only lock mode allowed outside of a transaction
LockModeType.Optimistic
- 如果实体指定了版本字段,则这是默认值。对于没有版本列的实体,不能保证使用这种类型的锁适用于任何 JPA 实现。如ObjectDB所述,此模式通常被忽略。在我看来,它的存在只是为了让您可以动态计算锁定模式并进一步传递它,即使锁定最终是乐观的。虽然不是很可能的用例,但提供一个选项来引用甚至默认值总是很好的 API 设计。
例子:
LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- 这是一个很少使用的选项。但如果你想锁定另一个实体引用这个实体,这可能是合理的。换句话说,即使实体未被修改,您也希望锁定使用该实体,但其他实体可能会被修改与该实体相关。
- 示例:我们有实体 Book 和 Shelf。可以将书添加到书架,但书没有对其书架的任何引用。锁定将一本书移到书架的动作是合理的,这样一本书在本次交易结束之前不会在另一个书架上结束(由于另一笔交易)。要锁定此操作,仅锁定当前书架实体是不够的,因为该书还不必在书架上。锁定所有目标书架也是没有意义的,因为它们在不同的交易中可能会有所不同。唯一有意义的是锁定书实体本身,即使在我们的例子中它没有被改变(它没有对其书架的引用)。
LockModeType.PESSIMISTIC_READ
- 这种模式类似于
LockModeType.PESSIMISTIC_WRITE
,但有一点不同:在某个事务在同一实体上设置写锁之前,它不应该阻止读取实体。它还允许其他事务使用LockModeType.PESSIMISTIC_READ
. WRITE 和 READ 锁之间的区别在此处 (ObjectDB)和此处 (OpenJPA)得到了很好的解释。如果一个实体已经被另一个事务锁定,任何锁定它的尝试都会引发异常。可以将此行为修改为等待一段时间释放锁,然后再抛出异常并回滚事务。为了做到这一点,javax.persistence.lock.timeout
在抛出异常之前指定要等待的毫秒数的提示。有多种方法可以在多个级别上执行此操作,如Java EE 教程。
- 这种模式类似于
LockModeType.PESSIMISTIC_WRITE
- 这是
LockModeType.PESSIMISTIC_READ
. 当WRITE
锁定到位时,JPA 在数据库的帮助下将阻止任何其他事务读取实体,而不仅仅是像READ
带锁那样写入。 - 没有规定如何在 JPA 提供者中与底层 DB 合作实现这一点。在您使用 Oracle 的情况下,我会说 Oracle 没有提供接近
READ
锁的东西。SELECT...FOR UPDATE
真的是一把WRITE
锁。这可能是休眠中的一个错误,或者只是一个决定,而不是实现自定义的“更软”READ
锁,WRITE
而是使用“更硬”锁。这主要不会破坏一致性,但不会使用READ
锁来保存所有规则。您可以使用READ
锁和长时间运行的事务运行一些简单的测试,以确定是否有更多的事务能够READ
在同一实体上获取锁。这应该是可能的,而没有WRITE
锁。
- 这是
LockModeType.PESSIMISTIC_FORCE_INCREMENT
- 这是另一种很少使用的锁定模式。但是,这是您需要组合
PESSIMISTIC
和OPTIMISTIC
机制的选项。PESSIMISTIC_WRITE
在以下情况下使用普通会失败:- 事务 A 使用乐观锁定并读取实体 E
- 事务 B 获得实体 E 的 WRITE 锁
- 事务 B 提交并释放 E 的锁
- 事务 A 更新 E 并提交
- 在步骤 4 中,如果事务 B 没有增加 version 列,则没有什么可以阻止 A 覆盖 B 的更改。锁定模式
LockModeType.PESSIMISTIC_FORCE_INCREMENT
将强制事务 B 更新版本号并导致事务 A 失败OptimisticLockException
,即使 B 使用的是悲观锁定。
- 这是另一种很少使用的锁定模式。但是,这是您需要组合
LockModeType.NONE
- 如果实体不提供版本字段,则这是默认设置。这意味着未启用锁定冲突将尽最大努力解决并且不会被检测到。这是在事务之外允许的唯一锁定模式