Win a copy of TensorFlow 2.0 in Action this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Paul Clapham
  • Bear Bibeault
  • Jeanne Boyarsky
Sheriffs:
  • Ron McLeod
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Jj Roberts
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • salvin francis
  • Scott Selikoff
  • fred rosenberger

Getting database deadlock with @Transactional in spring boot and hibernate

 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why I am getting deadlock in this code?

I tried to debug it and also read many article about deadlock prevention but could not get this. I have used synchronization, to make thread safe a block of code on the basis of `accountNumber`.

I am getting this `Transaction` object from an API and I want to lock my code on the basis of what the `Transaction` object contain. `Transaction` object contains info like debit/credit account number, amount etc.

Two threads should not be executed `executeTransaction` method simultaneously if there is any common `accountNumber` between them.

Here, `lockedAccount` is storing all accounts that are currently locked and two methods for locking and unlocking an `accountNumber`.

DAO / Repository layer.



   

for more information ,
my **accountDetails** table in database have three columns,

**id(int,primary key)**  

**AccountNumber(String,unique)**  

**amount(double)**


this is Service layer
where i am using `@Transactional` annotation for `executeTransaction` method.




but i am getting database deadlock in this code.
below is my error.

 
Ranch Hand
Posts: 111
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not a JPA/Hibernate expert, but that's not how I'd use the EntityManager. Why unwrap the session, why call saveOrUpdate etc.?
Get the objects via the EntityManager, update their state, and you should be done (as long as the entity is managed by the EntityManager, it will know when you modify it, and will save it without any extra calls when the transaction completes).
Also, I have never had to do this magic with ordering entity loading, and mixing in synchronisation via wait-notify. You can use optimistic locking (by adding a version number to the entity and to the DB table). It will sometimes fail, but that's a fact of life: someone has committed a transaction that changed the state of your object, so you're working on stale data. How you handle that optimistic lock failure depends on the business logic: most probably you'd have to propagate the exception and make the top-level call fail, e.g. reporting it to the user or returning an error code on your REST API.
 
Master Rancher
Posts: 4710
49
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Someone makes a call to do something to Account A.
The code in LockAccount (should be lockAccount) adds 'A' to the lockedAccounts Set.

The lock on lockedAccounts is released and the work is started on account 'A'.

Someone else comes in and tries to do something to Account A.
They get the lock on the Set, and then sit in the loop waiting for 'A' to disappear from the Set.

The original user finishes and now calls unlockAccount.
They then sit there waiting on the lock on lockedAccounts as it is currently being used by the other thread that is waiting for Account A to be removed.

Deadlock.

So that is your problem.
 
Istvan Kovacs
Ranch Hand
Posts: 111
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nope, lockedAccounts.wait() releases the lock on the Set's monitor. Also, this would not cause a DB-level deadlock.
 
Dave Tolls
Master Rancher
Posts: 4710
49
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good point.
Too quick off the mark (and stupidly didn't get as far as reading the exception).
 
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why not remove the synchronised block and place synchronised on the method,
private synchronised void LockAccount(String AccountNumber)

? Why is the set hash "static" that looks bad, also appears bad to have it outside the method ...
 
We should throw him a surprise party. It will cheer him up. We can use this tiny ad:
the value of filler advertising in 2020
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic