Environment
Spring-boot 2.6.6
Spring-data-jpa 2.6.6
Kotlin 1.6.10
mysql:mysql-connector-java 8.0.23
mysql 5.7 (innoDB)
Problem
A transaction commit happens during execution of my transactional method and I don't know why.
Code
@Transactional(isolation = Isolation.SERIALIZABLE)
fun login(username: String) {
userRepository.findByUsername(username)
?.let{
it.lastLoggedIn = LocalDateTime.now()
userRepository.save(it)
} :? run {
throw Exception("Not found User")
}
}
Result (from APM mornitoring tool)
-------------------------------------------------------------------------------------
p# # TIME T-GAP CONTENTS
-------------------------------------------------------------------------------------
[******] 18:50:13.493 0 Start transaction
- [000003] 18:50:13.639 40 spring-tx-doBegin(PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE)
- [000004] 18:50:13.639 0 getConnection jdbc:mysql://....(com.zaxxer.hikari.HikariDataSource#getConnection) 0 ms
- [000005] 18:50:13.641 2 [PREPARED] select ...{ellipsis} from user user0_ where user0_.username=? 0 ms
- [000006] 18:50:13.641 0 Fetch Count 1 1 ms
- [000007] 18:50:13.642 1 spring-tx-doCommit
- [000008] 18:50:13.643 1 [PREPARED] update user set last_logged_in=? where id=? 0 ms
[******] 18:50:13.646 3 End transaction
My though
I set transaction isolation level to serializable for some reason. As I know, it affects select query to make it with 'lock in share mode' to get a shared lock and an exclusive lock is needed for execution of the update query. An exclusive lock cannot be acquired on a row locked in shared mode so I thought it commits the transaction first to release the shared lock to get exclusive lock... but these query executions are in the same transaction, in the same DB connection, so in the same DB session. I think it doesn't make sense that the shared lock must be released to get exclusive lock in the same session.
What am I missing?