运行多线程数据库操作时获取LockAcquisitionException

时间:2018-11-16 12:41:54

标签: multithreading hibernate spring-data-jpa oracle12c spring-transactions

我正在将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下,并在服务方法处进行了注释。

有什么建议吗?

谢谢

0 个答案:

没有答案