Почему 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.

Другие вопросы по тегам