Получение LockAcquisitionException при выполнении многопоточных операций с БД - PullRequest
0 голосов
/ 16 ноября 2018

Я использую Spring Boot 2.1.0 с Hibernate-core-5.3.7 и Oracle 12C. У меня есть простой сервис, который выполняет операции удаления и вставки в рамках одной транзакции. Пока я вызываю сервис в одном потоке, сервис работает нормально. Но если я выполняю параллельные вызовы для нескольких операций Delete + Insert, некоторые потоки завершаются с ошибкой LockAcquisitionException.

Мой сервис разработан как показано ниже

@Service
public class PersonServiceImpl implements PersonService{

    @Autowired
    private PersonRepository personRepository;

    @Transactional
    public void performOperation(List<Person> persons) {

         //Delete all persons for say given person id
         personRepository.deletePersons(persons.get(0));

         personRepository.saveAll(persons);
         personRepository.flush();
    }

    @Repository
    public interface PersonRepository extends JpaRepository<Person,BigDecimal>, JpaSpecificationExecutor<Person>{

         @Query("delete FROM Person p WHERE p.person_id = :personId")
         @Modifying
         public void deletePersons(@Param("person_id") final Long personId);
    }

Целью этой операции является удаление всех людей для данного PersonId и вставка записей о лицах для того же PersonId.

При вызове этой службы в нескольких потоках я гарантировал, что каждый поток не будет переопределять другой, так как каждый поток будет иметь дело только с одним конкретным PersonId, и они уникальны. Таким образом, вопрос тупика между потоками исключен.

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

Исключение, которое я вижу, это

2018-11-16 06:10:25,839 WARN 
 org.hibernate.engine.jdbc.spi.SqlExceptionHelper [http-nio-9090-exec-7] SQL 
 Error: 60, SQLState: 61000
 2018-11-16 06:10:25,839 ERROR 
 org.hibernate.engine.jdbc.spi.SqlExceptionHelper [http-nio-9090-exec-7] 
 ORA-00060: deadlock detected while waiting for resource
 2018-11-16 06:10:25,855 TRACE 
 org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl [http-nio-9090-exec- 
 7] Starting after statement execution processing [ON_CLOSE]
 2018-11-16 06:10:25,857 TRACE 
 org.springframework.transaction.interceptor.TransactionAspectSupport [http- 
 nio-9090-exec-7] Completing transaction for 
 [org.springframework.data.jpa.repository.support.SimpleJpaRepository.flush] 
 after exception: javax.persistence.OptimisticLockException: 
 org.hibernate.exception.LockAcquisitionException: could not execute batch

Я не мог найти точно, что вызывает этот тупик в том же потоке. Что-то может быть связано с операцией удаления + вставки. Но оба работают в одной транзакции и в последовательности. Разве поток не выполняет SQL в той последовательности, в которой он представлен?

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

2018-11-16 06:10:03,403 TRACE 
 org.springframework.transaction.interceptor.TransactionAspectSupport [http- 
 nio-9090-exec-7] Don't need to create transaction for 
 [o.s.d.j.r.support.SimpleJpaRepository.deletePersons]: This method isn't 
 transactional.

Что это значит? Означает ли это, что «Удалить» не является транзакционным? Не имеет смысла, хотя? как это обернуто в @Transactional, аннотированный в методе обслуживания.

Есть предложения?

I

Спасибо

...