gpt4 book ai didi

java - lock() 方法中的 Grails StaleObjectStateException

转载 作者:搜寻专家 更新时间:2023-10-31 20:34:11 25 4
gpt4 key购买 nike

我在尝试锁定事务服务 (grails 2.3.8) 中的域对象时收到 StaleObjectStateException:

@Transactional
class AnalyticsService {
boolean newStreamView(Long streamId) {

Stream stream = Stream.lock(streamId) // The exception is launched here

当然,只有当有许多并发调用此服务时才会发生这种情况。如我所见,hibernate 正在尝试使用 ID 和版本参数进行锁定:

select id from stream where id =442 and version =305 for update

这失败了。如果我在该域类中禁用乐观锁定(版本:false),一切正常(hibernate 仅使用 id 来锁定行)。

发布于 Marc Palmer's Blog似乎是:

The only foolproof way to avoid StaleObjectException(s) while keeping optimistic locking ON, is to do all GORM work in transactions, and always load objects with Domain.lock(id). When using dynamic finders or criteria you will need to specify the “lock” option to have results pre-locked

他说我们应该保持乐观锁定。

是否有任何安全的方法来避免带有锁和乐观锁定的 StaleObjectStateException?

如果我禁用乐观锁定(版本:false),我还会遇到什么其他问题。我很担心这个,因为这个域类是从其他服务更新的?

提前致谢。

最佳答案

我们通过以下方式修复了 100% 的 StaleStateException/OptimisticLocking 问题:

  • 我们没有明确锁定任何东西。我们调整了代码流和对象,以使用以下方法最大限度地减少锁争用的机会
  • 从所有 Controller 中删除所有@Transactional 注释。将修改域对象的代码从 Controller 移到服务中。永远不要修改 Controller 中的域对象。仅委托(delegate)给服务(默认情况下是事务性的)来修改域对象。在这种情况下,您可能会这样做,但请确保 100% 的时间都这样做。
  • 不要禁用乐观锁定,这是有原因的。没有它,您将面临覆盖来自不同事务的更新的风险。一般来说,如果您要通过事务处理中的显式锁定或其他干预措施来解决此问题,您确实需要知道自己在做什么。
  • 请记住,如果您的域对象是 belongsTo/hasMany 关系的一部分,则在发生任何更新时,所有相关对象的版本号都会增加。因此,如果两个不同的进程正在更新对象图的不同部分,第一个提交将使第二个无效并导致这种情况。看看 Burt Beckwith 在这里说的是否中肯:https://www.youtube.com/watch?v=-nofscHeEuU .尽管他在这里谈论的是性能,但他提出的解决方案也最大限度地减少了版本号更新的级联。
  • 同样,您在这里似乎没有这样做,但是当我们只需要进行特定更新时,我们会尽量减少传递潜在脏的整个域对象。因此,当我们所做的只是设置状态时,我们可以说 orderService.setStatus('foo',orderId) 而不是 orderService.update(order) 并让该方法执行获取和更新。这缩短了发生 StaleState 的机会窗口,因为从获取到保存的时间很短。基本上,请确保您不会在脏域对象上停留的时间超过绝对必要的时间。

关于java - lock() 方法中的 Grails StaleObjectStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25301785/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com