Home > Mobile >  Avoiding write skews in Spring Data MongoDB
Avoiding write skews in Spring Data MongoDB

Time:02-10

I am trying to use Spring Data MongoDB transactions to avoid write skew errors. This diagram explains the flow that happens in my example. I also posted the source code as a whole in this repository.

My service method that reads and updates the same document is @Transactional:

fun nextMessage(id: Int, text: String) = transactionReadWrite(id, text)
    ?.let { messages.save(it) }

@Transactional
fun transactionReadWrite(id: Int, text: String) = threads.findById(id)
    ?.write(text)
    ?.let { (threadUpdate, previousLatest) ->
        threads.save(threadUpdate)
        log.info("Replacing \"${previousLatest.text}\" with \"${threadUpdate.latestMessage.text}\"")
        previousLatest
    }

But when I call nextMessage() with 5 different inputs in parallel, I can see some of them reading the same values at the same time, and then successfully updating the document:

15:37:06.964 : Opened connection [connectionId{localValue:3, serverValue:1264}] to localhost:27017
15:37:07.308 : Replacing "0" with "3"
15:37:07.308 : Replacing "0" with "4"
15:37:07.310 : Replacing "0" with "1"
15:37:07.430 : Opened connection [connectionId{localValue:5, serverValue:1265}] to localhost:27017
15:37:07.430 : Opened connection [connectionId{localValue:6, serverValue:1266}] to localhost:27017
15:37:07.435 : Replacing "1" with "2"
15:37:07.440 : Replacing "1" with "5"
15:37:07.447 : Replacing "5" with "another one"

How do you avoid write skew errors with Spring Data MongoDB transactions?

CodePudding user response:

According to the diagram, B3.update should not succeed, you need to use optmistic locking in the update, like updateOne({_id:xx, text:"1"}, $set: { text: "3" }) that will return 0 modified

Then Bobby needs to find the current entity and attempt the update again.

  • Related