隔离级别与乐观锁定 - 休眠,JPA

时间:2021-08-09 00:55:14

I have a web application where I want to ensure concurrency with a DB level lock on the object I am trying to update. I want to make sure that a batch change or another user or process may not end up introducing inconsistency in the DB.

我有一个Web应用程序,我想确保在我尝试更新的对象上使用数据库级锁定进行并发。我想确保批量更改或其他用户或进程最终可能不会在数据库中引入不一致。

I see that Isolation levels ensure read consistency and optimistic lock with @Version field can ensure data is written with a consistent state.

我看到隔离级别确保读取一致性,并且使用@Version字段进行乐观锁定可以确保数据以一致状态写入。

My question is can't we ensure consistency with isolation level only? By making my any transaction that updates the record Serializable(not considering performance), will I not ensure that a proper lock is taken by the transaction and any other transaction trying to update or acquire lock or this transaction will fail? Do I really need version or timestamp management for this?

我的问题是,我们不能只确保与隔离级别的一致性吗?通过使我的任何事务更新记录Serializable(不考虑性能),我是否不能确保事务采取正确的锁定以及任何其他尝试更新或获取锁定的事务或此事务将失败?我真的需要版本或时间戳管理吗?

2 个解决方案

#1


3  

Depending on isolation level you've chosen, specific resource is going to be locked until given transaction commits or rollback - it can be lock on a whole table, row or block of sql. It's a pessimistic locking and it's ensured on database level when running a transaction.

根据您选择的隔离级别,特定资源将被锁定,直到给定事务提交或回滚 - 它可以锁定整个表,行或块的sql。这是一个悲观的锁定,它在运行事务时在数据库级别上得到保证。

Optimistic locking on the other hand assumes that multiple transactions rarely interfere with each other so no locks are required in this approach. It is a application-side check that uses @Version attribute in order to establish whether version of a record has changed between fetching and attempting to update it.

另一方面,乐观锁定假设多个事务很少相互干扰,因此在这种方法中不需要锁定。它是一个应用程序端检查,它使用@Version属性来确定记录的版本是否在获取和尝试更新之间发生了变化。

It is reasonable to use optimistic locking approach in web applications as most of operations span through multiple HTTP request. Usually you fetch some information from database in one request, and update it in another. It would be very expensive and unwise to keep transactions open with lock on database resources that long. That's why we assume that nobody is going to use set of data we're working on - it's cheaper. If the assumption happens to be wrong and version has changed in between requests by someone else, Hibernate won't update the row and will throw OptimisticLockingException. As a developer, you are responsible for managing this situation.

在Web应用程序中使用乐观锁定方法是合理的,因为大多数操作都跨越多个HTTP请求。通常,您在一个请求中从数据库中获取一些信息,然后在另一个请求中更新它。使用长时间锁定数据库资源来保持事务处于打开状态是非常昂贵和不明智的。这就是为什么我们假设没有人会使用我们正在处理的数据集 - 它更便宜。如果假设恰好是错误的并且其他人的请求之间的版本发生了变化,那么Hibernate将不会更新该行并将抛出OptimisticLockingException。作为开发人员,您有责任管理这种情况。

Simple example. Online auctions service - you're watching an item page. You read its description and specification. All of it takes, let's say, 5 minutes. With pessimistic locking and some isolation levels you'd block other users from this particular item page (or all of the items even!). With optimistic locking everybody can access it. After reading about the item you're willing to bid on it so you click the proper button. If any other of users watching this item and change its state (owner changed its description, someone other bid on it) in the meantime you will probably (depending on app implementation) be informed about the changes before application will accept your bid because version you've got is not the same as version persisted in database.

简单的例子。在线拍卖服务 - 您正在观看项目页面。您阅读了它的描述和规范。所有这些都需要,比方说,5分钟。使用悲观锁定和一些隔离级别,您将阻止其他用户访问此特定项目页面(或甚至所有项目!)。通过乐观锁定,每个人都可以访问它。在阅读了您愿意出价的项目后,点击正确的按钮。如果其他任何用户在观看此项目并更改其状态(所有者更改了其描述,其他人对其进行了出价)的同时,您可能(根据应用实施情况)会在应用程序接受您的出价之前获知有关更改,因为您的版本是这与数据库中持久存在的版本不一样。

Hope that clarifies a few things for you.

希望能为您澄清一些事情。

#2


1  

Unless we are talking about some small, isolated web application (only app that is working on a database), then making all of your transactions to be Serializable would mean having a lot of confidence in your design, not taking into account the fact that it may not be the only application hitting on that certain database.

除非我们讨论一些小的,孤立的Web应用程序(只有正在处理数据库的应用程序),否则将所有事务都设置为Serializable将意味着对您的设计充满信心,而不考虑它的事实可能不是唯一一个应用于该特定数据库的应用程序。

In my opinion the incorporation of Serializable isolation level, or a Pessimistic Lock in other words, should be very well though decision and applied for:

在我看来,尽管决定并适用于:Serializable隔离级别或者悲观锁定的结合应该是非常好的:

  • Large databases and short transactions that update only a few rows
  • 只更新几行的大型数据库和短事务

  • Where the chance that two concurrent transactions will modify the same rows is relatively low.
  • 两个并发事务修改相同行的可能性相对较低。

  • Where relatively long-running transactions are primarily read-only.
  • 相对长时间运行的交易主要是只读的。

Based on my experience, in most of the cases using just the Optimistic Locking would be the most beneficial decision, as frequent concurrent modifications mostly happen in only small percentage of cases. Optimistic locking definately also helps other applications run faster (dont think only of yourself!).

根据我的经验,在大多数只使用乐观锁定的情况下,这将是最有利的决定,因为频繁的并发修改主要发生在很小比例的情况下。乐观锁定肯定也有助于其他应用程序运行得更快(不要只考虑自己!)。

So when we take the Pessimistic - Optimistic locking strategies spectrum, in my opinion the truth lies somewhere more towards the Optimistic locking with a flavor of serializable here and there.

因此,当我们采用悲观 - 乐观锁定策略谱时,在我看来,事实就在于更多地朝向乐观锁定,并且具有可序列化的味道。

I really cannot reference anything here as the answer is based on my personal experience with many complex web projects and from my notes when i was preapring to my JPA Certificate.

我真的不能在这里引用任何东西,因为答案是基于我对许多复杂网络项目的个人经验以及我在准备我的JPA证书时的笔记。

Hope that helps.

希望有所帮助。

#1


3  

Depending on isolation level you've chosen, specific resource is going to be locked until given transaction commits or rollback - it can be lock on a whole table, row or block of sql. It's a pessimistic locking and it's ensured on database level when running a transaction.

根据您选择的隔离级别,特定资源将被锁定,直到给定事务提交或回滚 - 它可以锁定整个表,行或块的sql。这是一个悲观的锁定,它在运行事务时在数据库级别上得到保证。

Optimistic locking on the other hand assumes that multiple transactions rarely interfere with each other so no locks are required in this approach. It is a application-side check that uses @Version attribute in order to establish whether version of a record has changed between fetching and attempting to update it.

另一方面,乐观锁定假设多个事务很少相互干扰,因此在这种方法中不需要锁定。它是一个应用程序端检查,它使用@Version属性来确定记录的版本是否在获取和尝试更新之间发生了变化。

It is reasonable to use optimistic locking approach in web applications as most of operations span through multiple HTTP request. Usually you fetch some information from database in one request, and update it in another. It would be very expensive and unwise to keep transactions open with lock on database resources that long. That's why we assume that nobody is going to use set of data we're working on - it's cheaper. If the assumption happens to be wrong and version has changed in between requests by someone else, Hibernate won't update the row and will throw OptimisticLockingException. As a developer, you are responsible for managing this situation.

在Web应用程序中使用乐观锁定方法是合理的,因为大多数操作都跨越多个HTTP请求。通常,您在一个请求中从数据库中获取一些信息,然后在另一个请求中更新它。使用长时间锁定数据库资源来保持事务处于打开状态是非常昂贵和不明智的。这就是为什么我们假设没有人会使用我们正在处理的数据集 - 它更便宜。如果假设恰好是错误的并且其他人的请求之间的版本发生了变化,那么Hibernate将不会更新该行并将抛出OptimisticLockingException。作为开发人员,您有责任管理这种情况。

Simple example. Online auctions service - you're watching an item page. You read its description and specification. All of it takes, let's say, 5 minutes. With pessimistic locking and some isolation levels you'd block other users from this particular item page (or all of the items even!). With optimistic locking everybody can access it. After reading about the item you're willing to bid on it so you click the proper button. If any other of users watching this item and change its state (owner changed its description, someone other bid on it) in the meantime you will probably (depending on app implementation) be informed about the changes before application will accept your bid because version you've got is not the same as version persisted in database.

简单的例子。在线拍卖服务 - 您正在观看项目页面。您阅读了它的描述和规范。所有这些都需要,比方说,5分钟。使用悲观锁定和一些隔离级别,您将阻止其他用户访问此特定项目页面(或甚至所有项目!)。通过乐观锁定,每个人都可以访问它。在阅读了您愿意出价的项目后,点击正确的按钮。如果其他任何用户在观看此项目并更改其状态(所有者更改了其描述,其他人对其进行了出价)的同时,您可能(根据应用实施情况)会在应用程序接受您的出价之前获知有关更改,因为您的版本是这与数据库中持久存在的版本不一样。

Hope that clarifies a few things for you.

希望能为您澄清一些事情。

#2


1  

Unless we are talking about some small, isolated web application (only app that is working on a database), then making all of your transactions to be Serializable would mean having a lot of confidence in your design, not taking into account the fact that it may not be the only application hitting on that certain database.

除非我们讨论一些小的,孤立的Web应用程序(只有正在处理数据库的应用程序),否则将所有事务都设置为Serializable将意味着对您的设计充满信心,而不考虑它的事实可能不是唯一一个应用于该特定数据库的应用程序。

In my opinion the incorporation of Serializable isolation level, or a Pessimistic Lock in other words, should be very well though decision and applied for:

在我看来,尽管决定并适用于:Serializable隔离级别或者悲观锁定的结合应该是非常好的:

  • Large databases and short transactions that update only a few rows
  • 只更新几行的大型数据库和短事务

  • Where the chance that two concurrent transactions will modify the same rows is relatively low.
  • 两个并发事务修改相同行的可能性相对较低。

  • Where relatively long-running transactions are primarily read-only.
  • 相对长时间运行的交易主要是只读的。

Based on my experience, in most of the cases using just the Optimistic Locking would be the most beneficial decision, as frequent concurrent modifications mostly happen in only small percentage of cases. Optimistic locking definately also helps other applications run faster (dont think only of yourself!).

根据我的经验,在大多数只使用乐观锁定的情况下,这将是最有利的决定,因为频繁的并发修改主要发生在很小比例的情况下。乐观锁定肯定也有助于其他应用程序运行得更快(不要只考虑自己!)。

So when we take the Pessimistic - Optimistic locking strategies spectrum, in my opinion the truth lies somewhere more towards the Optimistic locking with a flavor of serializable here and there.

因此,当我们采用悲观 - 乐观锁定策略谱时,在我看来,事实就在于更多地朝向乐观锁定,并且具有可序列化的味道。

I really cannot reference anything here as the answer is based on my personal experience with many complex web projects and from my notes when i was preapring to my JPA Certificate.

我真的不能在这里引用任何东西,因为答案是基于我对许多复杂网络项目的个人经验以及我在准备我的JPA证书时的笔记。

Hope that helps.

希望有所帮助。