Почему MongoDB не удалит старые документы, если ограниченная коллекция достигает максимального размера?
У меня есть ограниченная коллекция, которая была создана в java-коде:
this.collection = db.createCollection("stat", new BasicDBObject("capped", true).append("size", 200000000).append("max", 1000000));
Теперь в статистике по этой коллекции мы имеем:
/* 0 */
{
"ns" : "myDatabase.stat",
"count" : 12212,
"size" : 2146416,
"avgObjSize" : 175,
"storageSize" : 200003584,
"numExtents" : 1,
"nindexes" : 4,
"lastExtentSize" : 200003584,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 0,
"totalIndexSize" : 2272928,
"indexSizes" : {
"_id_" : 1259104,
"downloaded_1" : 335216,
"submitted_1" : 318864,
"retries_1" : 359744
},
"capped" : true,
"max" : 1000000,
"ok" : 1
}
И если я пытаюсь вставить документ в коллекцию с этим кодом:
BasicDBObject doc = new BasicDBObject().
append("downloaded", new Date(0)).
append("sessionId", sessionId).
append("group", group);
collection.update(new BasicDBObject("_id", request.getUrl()), new BasicDBObject("$set", doc), true, false);
Я ловлю эту ошибку:
com.mongodb.WriteConcernException: { "serverUsed" : "/127.0.0.1:27017" , "lastOp" : { "$ts" : 0 , "$inc" : 0} , "connectionId" : 16420 , "err" : "failing update: objects in a capped ns cannot grow" , "code" : 10003 , "n" : 0 , "ok" : 1.0}
at com.mongodb.CommandResult.getException(CommandResult.java:77)
at com.mongodb.CommandResult.throwOnError(CommandResult.java:110)
at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:102)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:142)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:115)
at com.mongodb.DBApiLayer$MyCollection.update(DBApiLayer.java:327)
at com.mongodb.DBCollection.update(DBCollection.java:178)
at com.mongodb.DBCollection.update(DBCollection.java:209)
at com.srg.hydra.monitoring.HydraStatistics.insert(HydraStatistics.java:63)
at com.srg.hydra.HydraSite.onSubmit(HydraSite.java:91)
at ru.decipher.site.AbstractSite.submit(AbstractSite.java:198)
at com.srg.hydra.Eip.start(Eip.java:48)
at com.srg.hydra.runner.DefaultHydraRunner.doCrawling(DefaultHydraRunner.java:180)
at com.srg.hydra.runner.DefaultHydraRunner$1.run(DefaultHydraRunner.java:155)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Что я делаю неправильно? И как это исправить? (исключить.drop() из этой коллекции и воссоздать) Спасибо за ответы!
1 ответ
Вы не можете обновить документ в закрытой коллекции.(Есть обходные пути, если вы прочитали весь мой ответ). Я сталкивался с этой проблемой в прошлом. Пожалуйста, найдите детали (и решение) этой проблемы в документации MongoDB ниже:
Рекомендации и ограничения
Вы можете делать только обновления документов на месте. Если операция обновления приводит к тому, что документ выходит за исходный размер, операция обновления завершится неудачно.
Если вы планируете обновить документы в закрытой коллекции, создайте индекс, чтобы эти операции обновления не требовали сканирования таблицы.
Если вы обновите документ в закрытой коллекции до размера, меньшего, чем его исходный размер, а затем вторичный сервер выполнит повторную синхронизацию с первичным сервером, вторичный сервер будет реплицировать и выделять пространство на основе текущего меньшего размера документа. Если первичный затем получает обновление, которое увеличивает документ до его первоначального размера, первичный примет обновление, но вторичный завершится неудачно с ошибочным обновлением: объекты в ограниченном ns не могут увеличить сообщение об ошибке.
Чтобы предотвратить эту ошибку, создайте вторичный сервер из моментального снимка одного из других современных членов набора реплик. Следуйте нашему руководству по снимкам файловой системы, чтобы заполнить ваш новый вторичный объект.
Заполнение вторичного файла снимком файловой системы - единственный способ гарантировать совместимость первичного и вторичного двоичных файлов. Снимки резервной копии MMS в этой ситуации недостаточны, так как вам нужно больше, чем содержимое вторичного устройства, чтобы соответствовать первичному.
Вы не можете удалить документы из закрытой коллекции. Чтобы удалить все записи из ограниченной коллекции, используйте команду emptycapped. Чтобы полностью удалить коллекцию, используйте метод drop().
Вы не можете осквернить ограниченную коллекцию.
Ограниченные коллекции, созданные после 2.2, по умолчанию имеют поле _id и индекс в поле _id. Ограниченные коллекции, созданные до 2.2, по умолчанию не имеют индекса в поле _id. Если вы используете ограниченные коллекции с репликацией до 2.2, вам следует явно создать индекс в поле _id.