left fetch join creates race condition with optimistic locking
if i use query to left join authors books the test suddenly doesnt pass
made a demo for simplicity
74 Replies
⌛
This post has been reserved for your question.
Hey @ayylmao123xdd! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
test
and the repo
somehow the left join makes two books be added to the same author even though theres a check for it to not happen
that's the code with pessemistic locking
How are you checking the version with optimistic locking? What are you actually modifying? How are you making the DB request?
oh
typo in the thread name
should be pessimistic locking
So you have a race condition with pessimistic locking?
yea after adding the query with left join fetch theres 2 books for the same author
even though theres a check in repository
to only allow one
its like left join fetch disables pessimistic locking
That statement just locks the
Author
AFAIK
Spring is doing exactly what you told it to doyea but in that case it shouldnt let two threads add a book at once
if pessimistic write prevents two threads from reading data at a time
@Lock
is only for the query you are executing AFAIKshouldnt it lock for the whole transaction tho
Where does it say that for
@lock
?ok nvm
Did you set a
PessimisticLockScope
?no
i was reading about that
but didnt check where to set it
actually no I think that's something slightly different
that would lock both
Author
and Book
yea
and i need the lock to work for the whole transaction ig
its quite weird considering it seems to lock for the whole transaction
when i dont use the query
even with eager fetching the test passes
i got open in view disabled btw
How is
addBook
called?
dont mind the names
How did you configure the test such that both threads can do stuff at the same time?
oh nvm it's just mockmvc
ye
so kinda weird
Can you log the text "start" before
findWithLockingById()
and "end" after save()
?
And then show what exactly is logged in what orderye
doin that now
seems like 2 read at the same time
even tho its pessimistic write
lmao
pessimistic read doesnt help just checked
just made a shocking discovery
if i do this
the test still doesnt pass
so ig the query annotation itself is the problem
and use eager fetch
same behavior when using entity graph
I tried to reproduce the issue and I get 0 books inserted
because of the test DB setup I think
h2 db
yes I'm using H2
but the thing is that normally, each thread for testing is isolated from the others
ye i was thinking it might be something with the cache before
but idk what it can be now
ah
so the test passes for me
😱
what did you change
I only made parts simpler
ah rerunning made it fail
disaster tbh
nah
hmmmmmmmmmmmmmmmm
ok so the locking part doesn't seem to be the issue for me
i deleted the
fetch from the query
and it seems to work ig
can you check if it helped for you
Where did you put the START log?
put the start log after the
findWithLockingById
see, it does pessimistic locking
it's just the isolation level
probably
i removed the fetch and now the tests pass somehow
well thats interesting
nvm it just stopped working
Which fetch?
the LEFT JOIN FETCH
ah that
but now it shows the tests as failed again
it was working for a few runs and now died
maybe its the test thats badly written
nevermind
i had fetch back to test if it works
I enabled debug logging for my reproducer which gives me some additional information
so try to run it with fetch
and without fetch
the results should be different
To me, it seems like the issue is that
findWithLockingById()
is just getting an old value
even though the other thread already completed
And I think this may be related to test transactionsi think it was because of the FETCH
at least for me
when i do it like this
it seems to pass
with this
2 books in repo
it also happens without FETCH for me
but it might happen more often with FETCH
ill rerun it a few times
without fetch
ran it 10 times all passed
it seems to work perfectly with hsqldb
try that
instead of H2
ok lemme swap
lol
for me its the opposite
hsql has 2 books
with h2 1
Can you try with a proper DB and testcontainers?
after swapping back to h2 works properly btw
yea ill check with mysql
btw I'm using LEFT JOIN FETCH
For me, this works with both HSQLDB and MySQL (testcontainers)
i ran it with mysql and both versions work
But with all DBs, it's running sequentially
with fetch and without
the difference is that it gets the old value with H2
btw I'm using this for logging
ill run again in hsqldb
but its weird that
in mysql both cases work
and in h2 and hsql only 1 case
and its the opposite one to them
testing with H2 is weird in general
What DB are you using in production?
mysql
lmao
Can you try H2 with a file DB?
now in hsql both scenarios dont work
ye ill grab one
without fetch passes
with fetch doesnt pass
yeah also fails for me without FETCH
yeah H2 do be weird
lets just blame the db
Stack Overflow
Entity fetched with pessimistic locking has outdated value
im testing some kind of small banking-ish service with mysql database.
im using 2nd level cache hibernate (possible source of problem?).
the data structure basically consists of 2 tables, a tab...
Stack Overflow
Spring data PESSIMISTIC_WRITE returns old DB value
I have this method in my interface which extends CrudRepository:
@Lock(LockModeType.PESSIMISTIC_WRITE)
Voucher findTop1ByUsedFalseAndProductOrderByIdAsc(Product product);
And this component:
@
With H2, it seems like it first loads the value and then locks the DB
yea i was reading these
ok gonna mark as solved
Post Closed
This post has been closed by <@452882919325827074>.