【问题标题】:simple optimistic lock question in jpa/spring/hibernatejpa/spring/hibernate中的简单乐观锁问题
【发布时间】:2011-03-01 11:01:41
【问题描述】:

我正在尝试使用重试拦截器实现基本的乐观锁机制。

所以问题是有一个带有属性responseCount 的对象Quiz。如果在测验更新过程中抛出乐观锁异常,将从重试拦截器中再次调用相应的更新方法。

事情是不对的,因为重试的方法每次都有相同的版本号,因此无论如何它都会使事务失败。

版本:10

过程 A: 开始更新测验,版本 10 过程乙: 开始更新测验,版本 10 过程乙: 完成更新测验,版本 11 过程A: 抛出乐观异常引发更新测验,重试过程A 在重试方法中,版本始终为 10

那我该怎么办?它应该自动增加版本以成功交易

【问题讨论】:

    标签: mysql hibernate spring jpa optimistic-locking


    【解决方案1】:

    乐观锁异常的处理方式如下:

    首先重新读取记录,获取新版本号和冲突事务写入的更新字段值。

    然后根据新值重新应用您的操作。 在您的情况下,这很简单——增加一个值是顺序无关的或可交换的。其他操作可能不容易重新应用——例如,假设事务都试图将问题跟踪器中的错误从一个工作流状态移动到另一个工作流状态。此转换只能发生一次,因此重试事务需要检查该错误是否仍处于该转换的有效状态,如果不是,它将向用户报告错误。

    【讨论】:

      【解决方案2】:

      在我看来,您想要更新测验,即使其他人在您背后更新了它(这会引发乐观异常)。如果是这种情况,为什么要在该实体上启用乐观日志记录?只需删除版本字段,它甚至无需重试即可工作。

      如果您真的想保留版本字段,请更改方法,使其从数据库获取测验,将新加载的测验的版本号复制到您的分离实例,然后合并分离实例以复制所有附加值的新值。

      【讨论】:

      • 我考虑使用乐观锁定的原因是为了防止例如许多并发用户参加测验并同时增加测验的 quizResponsesCount 属性的情况。现在我正在试验你的建议:我修改了我的服务层,它只从数据库中检索新对象(测验)然后更新它们。据我测试,重试机制以这种方式运行良好,这意味着它检测到乐观锁定,然后重试该方法,下次会成功。这样可以吗?
      【解决方案3】:

      你试图打败乐观锁 :D,这就提出了一个问题:你需要乐观锁吗?

      在不丢失以前数据的情况下,我可以看到重试的唯一合理方法是刷新对象,然后再次应用更改...无论如何,您将覆盖数据,这违背了乐观锁。

      在你的情况下,我要么完全禁用乐观锁定,要么将计数放在辅助表中,而不使用乐观锁定。

      【讨论】:

      • 计数确实需要锁定 -- 否则两个客户端可能会读取 '1',然后在正确计数为 '3' 时都写入 '2'。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-22
      • 2013-10-27
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      • 2017-10-02
      • 2014-03-07
      相关资源
      最近更新 更多