我正在将Spring Boot 2.1.0与Hibernate-core-5.3.7和Oracle 12C结合使用。我有一个简单的服务,该服务在同一事务下执行Delete和Insert操作。只要我在单个线程中调用服务,服务就可以正常工作。但是,如果我同时调用多个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的所有Person,并插入同一personId的Person记录。
在多个线程中调用此服务时,我确保每个线程都不会覆盖另一个线程,因为每个线程仅处理一个特定的PersonId,并且它们是唯一的。因此,排除了线程之间的死锁问题。
启用跟踪时,我注意到的是对于某些并发线程,在刷新时出现异常。我还注意到,如果我处理每个线程的大量记录而不是较小的记录,我经常会遇到例外情况。
我看到的异常是
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
我找不到在同一线程中导致此死锁的确切原因。可能与Delete + Insert操作有关。但是两者都在同一事务中并按顺序运行。刷新是否按提交顺序执行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下,并在服务方法处进行了注释。
有什么建议吗?
我
谢谢