Я использую Spring Data (spring-boot-starter-data-mongodb-reactive
версия 2.1.1
) и MongoDB 4.0.6 для записи двух новых документов, каждый из которых находится в разных коллекциях, в одной транзакции.Кажется, что все работает нормально при записи из одного потока, но как только появляется более одного потока, я получаю следующую ошибку:
com.mongodb.MongoCommandException: Command failed with error 24 (LockTimeout): 'Unable to acquire lock '{13748334747985680041: Metadata, 2219119701917210281}' within a max lock request timeout of '5ms' milliseconds.' on server localhost:27017. The full response is { "errorLabels" : ["TransientTransactionError"], "operationTime" : { "$timestamp" : { "t" : 1550655571, "i" : 35 } }, "ok" : 0.0, "errmsg" : "Unable to acquire lock '{13748334747985680041: Metadata, 2219119701917210281}' within a max lock request timeout of '5ms' milliseconds.", "code" : 24, "codeName" : "LockTimeout", "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1550655571, "i" : 35 } }, "signature" : { "hash" : { "$binary" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "$type" : "00" }, "keyId" : { "$numberLong" : "0" } } } })
Я прочитал этот ответ, предполагая, что:
Похоже, что создание индексов в тестах с глобальной блокировкой приводит к отставанию следующей блокировки транзакции и ее ожиданию до истечения времени ожидания запроса на блокировку.По сути, вы должны управлять созданием индекса, чтобы он не мешал транзакциям от клиента.
Но я не думаю, что это относится к моему делу.Я действительно могу воспроизвести ошибку, когда просто пишу один документ параллельно внутри транзакции, используя этот код:
@Document(collection = "my-dto")
data class MyDTO(var string : String, var date: Date, @Id var id: String? = null)
val mongoTemplate : ReactiveMongoTemplate = ...
val fluxWithSomeRandomStrings = ...
fluxWithSomeRandomStrings
.parallel()
.runOn(Schedulers.parallel())
.flatMap { string ->
mongo.inTransaction().execute { action ->
action.save(MyDTO(string, Date())).then()
}
}
.sequential()
.blockLast()
Как видите, MyDTO
не использует никаких индексов, так что это не должно бытьпричина проблемы.
Как я могу решить эту проблему и избежать LockTimeout
?