mongodb diskspace repair

Auto compacto el espacio eliminado en mongodb?



diskspace repair (4)

El documento mongodb dice que

Para compactar este espacio, ejecute db.repairDatabase () desde el shell mongo (tenga en cuenta que esta operación se bloqueará y es lenta).

en http://www.mongodb.org/display/DOCS/Excessive+Disk+Space

Me pregunto cómo hacer que el mongodb se elimine automáticamente en el espacio libre en el disco.

ps Almacenamos muchas tareas de descarga en mongodb, hasta 20 GB, y las terminamos en media hora.


En general, si no necesita reducir sus archivos de datos, no debe reducirlos en absoluto. Esto se debe a que "hacer crecer" sus archivos de datos en el disco es una operación bastante costosa y cuanto más espacio pueda asignar MongoDB en los archivos de datos, menos fragmentación tendrá.

Por lo tanto, debe intentar proporcionar la mayor cantidad de espacio de disco posible para la base de datos.

Sin embargo, si debe reducir la base de datos, debe tener en cuenta dos cosas.

  1. MongoDB hace crecer sus archivos de datos doblando para que los archivos de datos puedan ser de 64 MB, luego de 128 MB, etc. hasta 2 GB (en cuyo punto deja de doblar para mantener los archivos hasta 2 GB).

  2. Al igual que con la mayoría de las bases de datos ... para hacer operaciones como la reducción, tendrá que programar un trabajo por separado para hacerlo, no hay "autoshrink" en MongoDB. De hecho, de las principales bases de datos no SQL (odio ese nombre) solo Riak se autoenvolverá. Por lo tanto, tendrá que crear un trabajo utilizando el planificador de su sistema operativo para ejecutar una reducción. Puede usar un script bash, o tener un trabajo ejecutar un script php, etc.

Serverside Javascript

Puede usar el Javascript del lado del servidor para hacer el encogimiento y ejecutar ese JS a través del shell de mongo de forma regular a través de un trabajo (como cron o el servicio de programación de Windows) ...

Asumiendo una colección llamada foo , guardarías el siguiente javascript en un archivo llamado bar.js y ejecutar ...

$ mongo foo bar.js

El archivo javascript se vería como ...

// Get a the current collection size. var storage = db.foo.storageSize(); var total = db.foo.totalSize(); print(''Storage Size: '' + tojson(storage)); print(''TotalSize: '' + tojson(total)); print(''-----------------------''); print(''Running db.repairDatabase()''); print(''-----------------------''); // Run repair db.repairDatabase() // Get new collection sizes. var storage_a = db.foo.storageSize(); var total_a = db.foo.totalSize(); print(''Storage Size: '' + tojson(storage_a)); print(''TotalSize: '' + tojson(total_a));

Esto se ejecutará y devolverá algo así como ...

MongoDB shell version: 1.6.4 connecting to: foo Storage Size: 51351 TotalSize: 79152 ----------------------- Running db.repairDatabase() ----------------------- Storage Size: 40960 TotalSize: 65153

Ejecute esto según un cronograma (durante las horas pico) y estará listo para comenzar.

Colecciones limitadas

Sin embargo, hay otra opción, colecciones limitadas .

Las colecciones limitadas son colecciones de tamaño fijo que tienen una función de eliminación automática de FIFO de muy alto rendimiento (la antigüedad se basa en el orden de inserción). Son un poco como el concepto "RRD" si está familiarizado con eso.

Además, las colecciones limitadas, de alto rendimiento, mantienen el orden de inserción de los objetos en la colección; esto es muy poderoso para ciertos casos de uso como el registro.

Básicamente puede limitar el tamaño de (o el número de documentos) de una colección para decir ... 20 GB y una vez que se alcanza dicho límite, MongoDB comenzará a descartar los registros más antiguos y reemplazarlos por entradas más nuevas a medida que ingresen.

Esta es una gran manera de mantener una gran cantidad de datos, descartando los datos anteriores a medida que pasa el tiempo y manteniendo la misma cantidad de espacio de disco utilizado.


La ejecución de db.repairDatabase () requerirá que tenga un espacio igual al tamaño actual de la base de datos disponible en el sistema de archivos. Esto puede ser molesto cuando sabe que las colecciones que quedan o los datos que necesita conservar en la base de datos usarían actualmente mucho menos espacio del que se asigna y no tiene suficiente espacio para realizar la reparación.

Como alternativa, si tiene pocas colecciones que realmente necesita retener o solo desea un subconjunto de datos, puede mover los datos que necesita para guardar en una nueva base de datos y descartar la anterior. Si necesita el mismo nombre de base de datos, puede moverlos de nuevo a un db nuevo con el mismo nombre. Solo asegúrate de recrear cualquier índice.

use cleanup_database db.dropDatabase(); use oversize_database db.collection.find({},{}).forEach(function(doc){ db = db.getSiblingDB("cleanup_database"); db.collection_subset.insert(doc); }); use oversize_database db.dropDatabase(); use cleanup_database db.collection_subset.find({},{}).forEach(function(doc){ db = db.getSiblingDB("oversize_database"); db.collection.insert(doc); }); use oversize_database <add indexes> db.collection.ensureIndex({field:1}); use cleanup_database db.dropDatabase();

Una operación de exportación / soltar / importar para bases de datos con muchas colecciones probablemente logre el mismo resultado pero no he probado.

También como política puede mantener colecciones permanentes en una base de datos separada de sus datos transitorios / de procesamiento y simplemente colocar la base de datos de procesamiento una vez que se completen sus trabajos. Como MongoDB no tiene esquemas, no se perderán nada, excepto los índices, y su db y colecciones se volverán a crear cuando las inserciones de los procesos se ejecuten a continuación. Solo asegúrese de que sus trabajos incluyan la creación de índices nessecary en el momento adecuado.


Si está utilizando conjuntos de réplicas , que no estaban disponibles cuando esta pregunta se escribió originalmente, puede configurar un proceso para reclamar espacio automáticamente sin incurrir en problemas significativos de interrupción o rendimiento.

Para hacerlo, aprovecha las capacidades de sincronización inicial automática de un secundario en un conjunto de réplicas. Explicar: si apaga un secundario, borra sus archivos de datos y lo reinicia, el secundario se volverá a sincronizar desde cero desde uno de los otros nodos del conjunto (de manera predeterminada selecciona el nodo más cercano mirando la respuesta de ping) veces). Cuando se produce esta resincronización, todos los datos se reescriben desde cero (incluidos los índices), efectivamente hacen lo mismo que una reparación y el espacio en disco que reclama.

Al ejecutar esto en secundarios (y luego abandonar el proceso primario y repetir el proceso) puede reclamar efectivamente espacio en disco en todo el conjunto con una interrupción mínima. Debe tener cuidado si está leyendo desde secundarios, ya que esto hará que un secundario deje de girar durante un tiempo potencialmente prolongado. También debes asegurarte de que la ventana de tu oplog sea ​​suficiente para hacer una resincronización exitosa, pero generalmente es algo que querrás asegurarte si lo haces o no.

Para automatizar este proceso, simplemente necesitaría ejecutar un script para realizar esta acción en días separados (o similares) para cada miembro de su conjunto, preferiblemente durante su tiempo de silencio o ventana de mantenimiento. Una versión muy ingenua de este script se vería así en bash :

NOTA: ESTE ES BÁSICAMENTE EL CÓDIGO DE PSEUDO - PARA FINES ILUSTRATIVOS SOLAMENTE - NO UTILIZAR PARA SISTEMAS DE PRODUCCIÓN SIN CAMBIOS SIGNIFICATIVOS

#!/bin/bash # First arg is host MongoDB is running on, second arg is the MongoDB port MONGO=/path/to/mongo MONGOHOST=$1 MONGOPORT=$2 DBPATH = /path/to/dbpath # make sure the node we are connecting to is not the primary while (`$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval ''db.isMaster().ismaster''`) do `$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval ''rs.stepDown()''` sleep 2 done echo "Node is no longer primary!/n" # Now shut down that server # something like (assuming user is set up for key based auth and has password-less sudo access a la ec2-user in EC2) ssh -t user@$MONGOHOST sudo service mongodb stop # Wipe the data files for that server ssh -t user@$MONGOHOST sudo rm -rf $DBPATH ssh -t user@$MONGOHOST sudo mkdir $DBPATH ssh -t user@$MONGOHOST sudo chown mongodb:mongodb $DBPATH # Start up server again # similar to shutdown something like ssh -t user@$MONGOHOST sudo service mongodb start


Tengo otra solución que podría funcionar mejor que hacer db.repairDatabase () si no puede permitirse que el sistema se bloquee, o no tiene el doble de almacenamiento.

Debe usar un conjunto de réplicas.

Lo que pensé una vez que eliminó todo el exceso de datos que está engullendo su disco, detuvo una réplica secundaria, borró su directorio de datos, lo inició y lo dejó resincronizar con el maestro.

El proceso lleva mucho tiempo, pero solo debería costar unos segundos de tiempo de inactividad, cuando lo hace rs.stepDown ().

Además, esto no puede ser automatizado. Bueno, podría, pero no creo que esté dispuesto a intentarlo.