Я использую 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
Спасибо