Intershop ORMException не удалось обновить - обновите ORMObject

В кластерной межшопной среде мы видим много сообщений об ошибках. Я подозреваю, что связь между серверами приложений ненадежна.

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);
    }

3 ответа

Вы получаете эту ошибку, потому что оптимистическая блокировка "терпит неудачу". Чтобы лучше понять проблему, я попытаюсь объяснить, как работает оптимистическая блокировка, в частности на уровне Intershop ORM.

В таблицах PO есть столбец с именем OCA (OCA == оптимистический атрибут управления?). Представьте, что два сервера (или два разных потока / транзакции) пытаются обновить одну и ту же строку в таблице. Из соображений производительности по умолчанию блокировка БД не задействована (например, с помощью команды select for update). Вместо этого первый поток / сервер увеличивает OCA на единицу, когда он успешно обновляет строку в своей транзакции.

Второй поток / сервер знает значение ОСА со времени, когда он создал свое собственное состояние. Затем он пытается обновить строку, выполнив аналогичный запрос:

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

Поскольку OCA уже увеличен первым потоком / сервером, это обновление завершается неудачно (на самом деле - обновляет 0 строк), и исключение, которое вы разместили выше, генерируется, когда уровень ORM обнаруживает, что ни одна строка не была обновлена.

Ваша проблема не в межсерверной связи, а в том, что либо:

  • несколько серверов / потоков пытаются обновить один и тот же объект;
  • в базе данных есть прямые обновления, которые обходят уровень ORM (менее вероятно);

Для решения этой проблемы вы можете:

  1. Избегайте этой ситуации вообще (очень рекомендую мной:-));
  2. Используйте блокировку ISH (очень громоздко);
  3. Используйте пессимистическую блокировку, поддерживаемую уровнем ISH ORM и Oracle (остерегайтесь потенциальных проблем с производительностью, взаимоблокировок, ошибок);
  4. Используйте блокировку Java - но поскольку серверы работают в разных JVM, это редко вариант;

OFFTOPIC замечания: я не уверен, почему вы используете getObjectsBySQLWhere когда вы знаете первичный ключ (UUID). Насколько я помню ORMObjectCollection-s должны быть закрыты, если не повторены полностью.

ОБНОВЛЕНИЕ: Если кластер не настроен правильно и многоадресные передачи не могут быть получены от узлов, вы не сможете решить проблемы программным путем.

"ORMObject.refresh()" помечает кэшированное общее состояние как недействительное. Следующий доступ к объекту перезагружает состояние из базы данных. Это влияет на производительность и увеличивает нагрузку на сервер базы данных.

НО: метод refresh () не перезагружает состояние экземпляра PO, если оно уже назначено текущей транзакции.

Было бы лучше, чтобы исследовать и исправить проблемы связи с сервером.

Другая возможность состоит в том, что это не проблема связи (многоадресная рассылка между узлами в кластере, я полагаю), а просто два запроса, пытающихся обновить корзину одновременно. Пример два ajax-запроса на обновление чего-либо в корзине.

Я бы не пытался "исправить" форму, это только принесло бы больше вреда, чем пользы. Скорее исследуйте дальше и отправьте назад больше информации.

Другие вопросы по тегам