Я пытаюсь отправить около 150 тысяч обновлений в базу данных Mongo (v 4.2.9, работающая в Windows, реплика этапа с двумя узлами), используя BulkWrite для драйвера С# (v2.11.6), и похоже, что это невозможно. Проект .Net Framework 4.7.2.
Документация драйвера Mongo С# ужасна, но каким-то образом на форумах и с большим количеством поиска в Google я, наконец, смог найти способ, как запустить около 150 000 обновлений с помощью пакета, примерно так (немного упрощенно для SO):
client = new MongoClient(connString);
database = client.GetDatabase(db);
// Build all the updates
List<UpdateOneModel<GroupEntry>> updates = new List<UpdateOneModel<GroupEntry>>();
foreach (GroupEntry groupEntry in stats)
{
FilterDefinition<GroupEntry> filter = Builders<GroupEntry>.Filter.Eq(e => e.Key, groupEntry.Key);
UpdateDefinitionBuilder<GroupEntry> update = Builders<GroupEntry>.Update;
var groupEntrySubUpdates = new List<UpdateDefinition<GroupEntry>>();
if (groupEntry.Value.Clicks != 0)
groupEntrySubUpdates.Add(update.Inc(u => u.Value.Clicks, groupEntry.Value.Clicks));
if (groupEntry.Value.Position != 0)
groupEntrySubUpdates.Add(update.Set(u => u.Value.Position, groupEntry.Value.Position));
UpdateOneModel<GroupEntry> groupEntryUpdate = new UpdateOneModel<GroupEntry>(filter, update.Combine(updates));
groupEntryUpdate.IsUpsert = true;
updates.Add(groupEntryUpdate);
}
// Now BulkWrite them in transaction to make sure data are consistent
IClientSessionHandle session = client.StartSession();
session.StartTransaction();
IMongoCollection<GroupEntry> collection = database.GetCollection<GroupEntry>(collectionName);
// Following line FAILS after some time
BulkWriteResult<GroupEntry> bulkWriteResult = collection.BulkWrite(session, updates);
if (!bulkWriteResult.IsAcknowledged)
throw new Exception("Mongo BulkWrite is not acknowledged!");
session.CommitTransaction();
Проблема в том, что я продолжаю получать следующее исключение:
{
"operationTime":Timestamp(1612737199,
1),
"ok":0.0,
"errmsg":"Exec error resulting in state FAILURE :: caused by :: operation was interrupted",
"code":262,
"codeName":"ExceededTimeLimit",
"$clusterTime":{
"clusterTime":Timestamp(1612737199,
1),
"signature":{
"hash":new BinData(0,
"ljcwS5Gf2JBpEu/OgPFbvRqclLw="")",
"keyId":"NumberLong(""6890288652832735234"")"
}
}
}
Кто-нибудь знает? Документы драйвера Mongo С# совершенно бесполезны. Похоже, мне нужно каким-то образом установить свойство $maxTimeMS, но это невозможно в BulkInsert. Я пытался:
- Перезагружается и перестраивается
- Различные версии MongoDriver
- Установите гораздо большие тайм-ауты для всех свойств тайм-аута в MongoClient и сеансе.
- Создавайте небольшие партии для массовой записи (до 1000 элементов в партии). Сбой после 50-100 обновлений.
- Провел часы и часы в бесполезных документах Mongo и Mongo JIRA
Пока не повезло. Самое смешное, что тот же подход работает с драйвером С# 2.10.3 на .Net CORE 3.1 (да, я пробовал) даже с большими партиями (около 300 тысяч обновлений).
Что мне не хватает?
ИЗМЕНИТЬ:
Я попытался установить maxCommitTime на 25 минут, основываясь на комментариях dododo, например:
IClientSessionHandle session = client.StartSession(new ClientSessionOptions()
{
DefaultTransactionOptions = new TransactionOptions(new Optional<ReadConcern>(ReadConcern.Default),
new Optional<ReadPreference>(ReadPreference.Primary),
new Optional<WriteConcern>(WriteConcern.Acknowledged),
new Optional<TimeSpan?>(TimeSpan.FromMinutes(25)))
});
Теперь при фиксации выдается исключение: NoSuchTransaction — транзакция 1 была прервана. Мы проверили лог-файл MongoDB и обнаружили там новую ошибку:
Прерывание транзакции с txnNumber 1 в сеансе 09ea7755-7148-43e8-83d8-8bf58c211bda, поскольку он выполняется дольше, чем «transactionLifetimeLimitSeconds».
Согласно документам, по умолчанию это 60 секунд. Итак, мы установили его на 5 минут, и теперь он работает.
Итак, спасибо, дододо, за то, что указал мне правильное направление.
В любом случае, было бы действительно здорово, если бы команда Mongo лучше описывала ошибки и писала документацию выше базовых операций CRUD.
maxTimeMS
работает только с курсорами. Я подозреваю, что это поведение транзакции, а не массовые операции, поэтому, предположительно, ваша операция работает без сеанса. Если это так, попробуйте установитьmaxCommitTime
в параметрах транзакции. - person dododo   schedule 08.02.2021that the same approach works on c# driver 2.10.3 on .Net CORE 3.1
- это выглядит очень подозрительно, можете сделать еще попытки? Например, проверить этот случай еще раз для той же версии базы данных, той же структуры данных/записей с одинаковыми индексами как для net framework, так и для net core для 2.10.3 и 2.11.6? - person dododo   schedule 08.02.2021