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

时间:2017-01-19 20:34:42

标签: database hibernate jpa orm

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

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

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

2 个答案:

答案 0 :(得分:5)

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

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

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

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

希望为您澄清一些事情。

答案 1 :(得分:1)

除非我们讨论一些小的,孤立的Web应用程序(只有在数据库上工作的应用程序),否则将所有事务都设置为Serializable意味着对您的设计有很大的信心,而不是考虑到事实上,它可能不是唯一的应用程序打击某个数据库。

在我看来,尽管决定并申请了,但序列化隔离级别或者悲观锁定的结合应该非常好:

  • 仅更新几行的大型数据库和简短交易
  • 两个并发事务修改相同行的可能性相对较低。
  • 相对长时间运行的交易主要是只读的。

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

因此,当我们采用悲观 - 乐观的锁定策略谱时,在我看来,事实就在于乐观锁定,而且可以在这里和那里进行序列化。

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

希望有所帮助。