Why transaction is committed in the middle of transactional method execution?

Viewed 32

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?

0 Answers
Related