1

在集群的 intershop 环境中,我们会看到很多错误消息。我怀疑应用程序服务器之间的通信不可靠。

Caused by: com.intershop.beehive.orm.capi.common.ORMException: 
Could not UPDATE object: com.intershop.beehive.bts.internal.orderprocess.basket.BasketPO

本地应用程序服务器是否有安全的方法来加载最新实例。

   BasketPO basket = null;
        try{
            BasketPOFactory factory = (BasketPOFactory) NamingMgr.getInstance().lookupFactory(BasketPOFactory.FACTORY_NAME);
            try(ORMObjectCollection<BasketPO>baskets = factory.getObjectsBySQLWhere("uuid=?", new Object[]{basketID},CacheMode.NO_CACHING);){
                if(null != baskets && !baskets.isEmpty()){
                    basket = baskets.stream().findFirst().get();
                }
            }
        }
        catch(Throwable t){
            Logger.error(this, t.getMessage(),t);
        }

ORMObject#refresh 方法有帮助吗?

    try{
        if(null != basket)
              basket.refresh();
    }
    catch(Throwable t){
        Logger.error(this, t.getMessage(),t);
    }
4

3 回答 3

2

您遇到该错误是因为乐观锁“失败”。为了更好地理解这个问题,我将尝试解释乐观锁定是如何工作的,特别是在 Intershop ORM 层中。

PO 表中有一个名为 OCA 的列(OCA == 乐观控制属性?)。想象一下,两个服务器(或两个不同的线程/事务)尝试更新表中的同一行。出于性能原因,默认情况下不涉及数据库锁定(例如,通过发出 select for update)。相反,当它在其事务中成功更新行时,第一个线程/服务器将 OCA 增加一个。

第二个线程/服务器从创建自己的状态时就知道 OCA 的值。然后它尝试通过发出类似的查询来更新该行:

UPDATE ... OCA = OCA + 1 ... WHERE UUID = <uuid> AND OCA = <old_oca>

由于 OCA 已经由第一个线程/服务器增加,因此此更新失败(实际上 - 更新 0 行),并且当 ORM 层检测到没有更新行时,将引发您在上面发布的异常。

您的问题不是服务器间通信,而是以下事实:

  • 多个服务器/线程尝试更新同一个对象;
  • 数据库中有绕过 ORM 层的直接更新(不太可能);

要解决这个问题,您可以:

  1. 完全避免这种情况(我强烈推荐:-));
  2. 使用ISH锁定框架(非常繁琐的imHo);
  3. 使用 ISH ORM 层和 Oracle 支持的悲观锁定(注意潜在的性能问题、死锁、错误);
  4. 使用 Java 锁定 - 但由于服务器在不同的 JVM-s 中运行,这很少是一种选择;

OFFTOPIC 备注:getObjectsBySQLWhere当你知道主键(uuid)时,我不确定你为什么使用。据我记得ORMObjectCollection-s 如果没有完全迭代,应该关闭。

更新:如果集群配置不正确并且无法从节点接收多播,您将无法以编程方式解决问题。

于 2017-08-10T05:29:30.267 回答
0

“ORMObject.refresh()”将缓存的共享状态标记为无效。对对象的下一次访问从数据库重新加载状态。这会影响性能并增加数据库服务器负载。

但是:如果“refresh()”方法已经分配给当前事务,则它不会重新加载 PO 实例状态。

最好调查并修复服务器通信问题。

于 2017-08-09T09:04:13.970 回答
0

另一种可能性是这不是通信问题(我假设集群中节点之间的多播),而是只有两个请求试图同时更新购物篮。示例二 ajax 请求更新篮子上的东西。

我会避免尝试“修复” orm,它只会弊大于利。而是进一步调查并回发更多信息。

于 2017-08-10T04:38:03.000 回答