如何处理GORM中的乐观锁定失败

时间:2016-04-29 19:40:48

标签: hibernate grails gorm

当我们的系统负载很重,几十个并发事务时,我得到乐观锁定失败错误。应用程序在与单个数据库实例通信的多个服务器上进行负载平衡。

据我所知,其核心是GORM乐观锁定机制。新线程在原始线程中加载域变量时会更改域对象属性并尝试更改。

如果是这样,处理它的最佳方法是什么?我不想处理错误,因为滚动整个事务并不是一个好的解决方案。

我有什么选择?

  1. 声明版本为false?这是否会阻止对该域对象的乐观锁定并允许并发线程更改它,即使这意味着在没有错误的情况下相互覆盖?

  2. 通过使用Object.lock(id)检索域对象的持续时间来锁定域对象?如果没有测试,很难说性能有多大,但这是最好的方法吗?

  3. 还有其他选择吗?

  4. 下面包含相关代码。如果锁定是最好的方法,那么我如何实现它,因为Object是从未保存的父对象访问子节点的?

    ProductOrderService中的第390行。

    private rollbackInventory(Order order) {
        order.items.each {orderItem->
            Product product = orderItem.product
            product.increaseQuantityBy(orderItem.qty)
            product.save(flush: true)
        }
    }
    

    Product domain类中的increaseQuantityBy方法如下所示:

    .......
    
    Integer qty
    
    .......
    
    public void increaseQuantityBy(Integer change) {
        changeQuantityBy(change)
    }
    
    public void decreaseQuantityBy(Integer change) {
        changeQuantityBy(-change)
    }
    
    private void changeQuantityBy(Integer change) {
        qty += change
    }
    

    这是错误:

    2016-04-29 08:08 -- ERROR-grails.app.controllers.com.shop.order.ProductOrderController:Exception occurred. Object of class [com.shop.Product] with identifier [5774]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.shop.Product#5774]
    org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Object of class [com.shop.Product] with identifier [5774]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.shop.Product#5774]
            at com.shop.order.ProductOrderService$_rollbackInventory_closure5.doCall(ProductOrderService.groovy:390)
            at com.shop.order.ProductOrderService.rollbackInventory(ProductOrderService.groovy:387)
            at com.shop.order.ProductOrderService.processOrder(ProductOrderService.groovy:178)
            at com.shop.order.ProductOrderController.order(ProductOrderController.groovy:240)
            at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:198)
            at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
            at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
            at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:53)
            at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:62)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
            at java.lang.Thread.run(Thread.java:745)
    Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.shop.Product#5774]
            ... 12 more
    

0 个答案:

没有答案