Сбой команды MongoDB с ошибкой 24 (LockTimeout) с одновременными транзакциями - PullRequest
0 голосов
/ 20 февраля 2019

Я использую 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?

...