• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Rob Spoor
  • Devaka Cooray
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Jj Roberts
  • Al Hobbs
  • Piet Souris

Getting database deadlock with @Transactional in spring boot and hibernate

 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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: 116
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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.
 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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: 116
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
    Number of slices to send:
    Optional 'thank-you' note:
  • 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 ...
 
You showed up just in time for the waffles! And this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic