Getting LockAcquisitionException while running multi Threaded DB operations

Viewed 3633

I'm using Spring Boot 2.1.0 with Hibernate-core-5.3.7 and Oracle 12C. I have simple service, that performs Delete and Insert operations under same transaction. As long as I call the service in a single thread, service is working fine. But If I make concurrent calls for several Delete + Insert operations, some of the threads are failing with LockAcquisitionException.

My Service is designed as below

@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);
    }

The intention of this operation is to delete all Persons for a given PersonId, and insert the Person records for the same personId.

When calling this service in multiple threads, I ensured that each thread will not override the other, as each thread will deal only with one particular PersonId and they are unique. So, the question of deadlock between the threads is ruled out.

When enabled the Trace, what I noticed is that for some of the concurrent threads, getting exception at the time flush. I also noticed that I see the exception often, if I'm dealing with huge volume of records per thread, than smaller set.

The exception I see is

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

I could not find exactly what is causing this deadlock within the same thread. Something might to do with Delete + Insert operation. But both are running in same transaction and in sequence. Does not the flush execute the SQL in the sequence they are submitted ?

I also noticed in logs, every time I call the service whether in a single thread or concurrently.

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.

What does this mean? Does it mean Delete is not transactional? Does not make sense though? as it is wrapped under @Transactional annotated at service method.

Any suggestions ?

I

Thanks

0 Answers
Related