Несколько потребителей пытаются обновить одну и ту же строку таблицы Mysql (версия 5.7).Как исправить проблему одновременного обновления - PullRequest
0 голосов
/ 04 октября 2018

Несколько потребителей пытаются обновить поля «ОбработанныеРекордс» и «ЭрредРекордс» в JobTracker.Но я столкнулся с проблемой, когда случайные значения обновляются в этих столбцах.Mysql находится на уровне изоляции по умолчанию (MySQL версии 5.7)

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

Обратите внимание: 1. Любое решение, которое изменяет уровень изоляции для всей БД, бесполезно, так как это повлияет на другие потоки в приложении.2. Оба параметра «processRecords» и «erredRecords» имеют тип Long.

@Override
@Transactional
public Boolean updateRecords(Long jobTrackerId, Long processedRecords, Long erredRecords) {
    try{
        JobTracker jobTracker = getEntityManager(true).find(JobTracker.class, jobTrackerId);
        getEntityManager(true).lock(jobTracker, LockModeType.PESSIMISTIC_WRITE);
        if(jobTracker == null){
            return false;
        }
        if(processedRecords!=null){
            jobTracker.setProcessedRecords(processedRecords);
        }
        if(erredRecords!=null){
            jobTracker.setErredRecords(erredRecords);
        }
        if(jobTracker.getErredRecords() != null && jobTracker.getProcessedRecords() != null && jobTracker.getTotalRecords() != null){
            if(jobTracker.getErredRecords() + jobTracker.getProcessedRecords() == jobTracker.getTotalRecords()){
                jobTracker.setStatus("Completed");
            }else if(jobTracker.getErredRecords() + jobTracker.getProcessedRecords() > jobTracker.getTotalRecords()){
                jobTracker.setStatus("Erred");
            }
        }
        getEntityManager(true).merge(jobTracker);
        return true;
    }catch(PersistenceException e){
        logger.error("For job id:" + jobTrackerId + " Exception while updating the jobTracker records data", e);
        return false;
    }catch (Exception e){
        logger.error("For job id:" + jobTrackerId + "Generic Exception while updating the jobTracker records data",e);
        return false;
    }
}

1 Ответ

0 голосов
/ 06 октября 2018

Используя аннотацию @Transactional, мы можем установить уровень изоляции управляемого транзакционным методом Spring.Это означает, что транзакция в этом методе будет иметь этот уровень изоляции.В вашем случае все, что вам нужно сделать, это следующее.

@Transactional(isolation=Isolation.READ_COMMITTED)

Теперь, если бы вы установили уровень изоляции для всей вашей БД, вы бы сделали следующее.

<property name="hibernate.connection.isolation">2</property>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...