在集群的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);
}
答案 0 :(得分:1)
您遇到此错误,因为乐观锁定“失败”。为了更好地理解这个问题,我将尝试解释乐观锁定在Intershop ORM层中的工作原理。
PO表中有一个名为OCA的列(OCA ==乐观控制属性?)。想象一下,两个服务器(或两个不同的线程/事务)尝试更新表中的同一行。出于性能原因,默认情况下不涉及DB锁定(例如,通过发出select for update)。相反,第一个线程/服务器在其事务中成功更新行时将OCA递增1。
第二个线程/服务器从创建自己的状态时就知道OCA的值。然后它尝试通过发出类似的查询来更新行:
UPDATE ... OCA = OCA + 1 ... WHERE UUID = <uuid> AND OCA = <old_oca>
由于OCA已经被第一个线程/服务器递增,因此更新失败(实际上 - 更新0行),并且当ORM层检测到没有更新行时,抛出上面发布的异常。
您的问题不是服务器间通信,而是以下事实:
要解决此问题,您可以:
OFFTOPIC备注:我不知道为什么在知道主键(uuid)时使用getObjectsBySQLWhere
。据我记得ORMObjectCollection
- 如果没有完全迭代,应该关闭。
更新:如果未正确配置群集并且无法从节点接收多播,则无法以编程方式解决问题。
答案 1 :(得分:0)
&#34; ORMObject.refresh()&#34;将缓存的共享状态标记为无效。下一次访问该对象将从数据库重新加载该状态。这会影响性能并增加数据库服务器负载。
BUT: &#34;刷新()&#34;如果PO实例状态已分配给当前事务,则不会重新加载PO实例状态。
最好调查并修复服务器通信问题。
答案 2 :(得分:0)
其他可能性是它不是通信问题(我假设集群中的节点之间的多播),但是只有两个请求同时尝试更新篮子。示例二ajax请求更新篮子上的内容。
我会避免尝试&#34;修复&#34;在这个问题上,它只会造成弊大于利。而是进一步调查并发回更多信息。