mercoledì 10 febbraio 2016

MongoDB - Backup di grandi db

Nasce, molte volte, il problema di eseguire un backup su una grande mole di dati.

Uno dei modi possibili (vedi doc) è prendere i file dei db di mongo e semplicemente copiarli.

Il nostro problema nasce che non tutti i db devono essere backuppati per essere ribaltati, e il nome dei file di archivio di mongo non sono parlanti.

Una soluzione e configurare ogni db in una singola cartella con i parametri di configurazione

storage.directoryPerDB

un'altro parametro ottimo è:

storage.wiredTiger.engineConfig.directoryForIndexes

i db vengono archiviati in cartelle separate e divisi in due cartelle collections e index così eventualmente in fase di copia dei dati è possibile escludere le folder degli indici risparmiando spazio e tempo.


Questa configurazione necessita di un mongodump e un mongorestore. In caso di ReplicaSet basta fermare il primario, svuotare le cartelle, cambiare le conf e attendere che si replichi con il secondario che è diventato primario. Al termine il primario diventa nuovamente secondario e viceversa.

MongoDB version 3.0.7

martedì 9 febbraio 2016

MongoDB - Script to Delete all collection with exclusion

Semplice script per eliminare tutte le collection di un db ad esclusione di una lista di collection.


function deleteAllCollection(dbName,excludeCollection){
var dbOne = db.getSisterDB(dbName);
for(var colName in dbOne.getCollectionNames()){
var collectionName = dbOne.getCollectionNames()[colName];
if(!collectionName || collectionName == "")
continue;
if(excludeCollection.indexOf(collectionName) > -1)
continue;
dbOne[collectionName].drop();
};
};
deleteAllCollection("<dbName>",["<exclude_col_name_1>","<exclude_col_name_2>","<exclude_col_name_N>"]]);
//run with
// mongo --host <host_name> --port <port_name> DropCollectionInDB.js

giovedì 4 febbraio 2016

MongoDB - Script per eseguire una purge di dati dalle varie collection di log

Capita alle volte di voler svuotare delle collection che contengo informazioni di log.

Questo script partendo dal nome del server ricerca tutti i db che iniziano con un certo nome, cicla tutte le collection (ad esclusione di quelle specificate), esegue una query per conteggiare i record che devono essere eliminati e poi elimina in base al numero di giorni che vogliamo mantenere sui log a partire da oggi.

Il campo di controllo di data è chiamato ts.



/*
la funzioanlità ricerca nel server tutti i db like <db_like_name> e per ogni collecion presente nel singolo db
esegue una eliminazione per spurgare i log.
per eseguire lo script
./mongo --host <indirizzo_host> --port <porta> PurgeLogCollection.js --quiet --eval "var deleteData=false;var beforePurgeDay=200;"
parametri in eval
deleteDate = true|false (se false visualizza solo questo che dovrà fare senza eliminare default false)
beforePurgeDay = indica i giorni indietro da oggi che deve eliminare, default 365.
*/
//set to True to enable DEBUG
var debug = false;
//name db inde of
var dbNameIndexOf = "<db_like_name>";
//Collection to exclude
var excludeCollection = ['local','<collection_name_to_eclude_tio_purge>'];
if(!deleteData)
var deleteData = false;
if(typeof(db) === 'undefined' || !db){
print('ERROR --> specify serve name --host <host> --port <port>');
quit(1);
}
if(typeof(beforePurgeDay) === 'undefined' || !beforePurgeDay){
var beforePurgeDay = 365;
print('INFO --> set default beforePurgeDay = ' + beforePurgeDay + ' to change add var beforePurgeDay=200; to eval');
}
function print_debug(pretext, text){
if(!debug)
return;
if(text === 'object' || typeof text === 'object' || text === '[object Object]')
print(pretext + "==>" + JSON.stringify(text));
else
print(pretext + "==>" + text);
}//print_debug(pretext, text)
function convertDate(d) {
function pad(s) {
return (s < 10) ? '0' + s : s;
}
return [pad(d.getDate()), pad(d.getMonth()+1), d.getFullYear()].join('/');
}//convertDate(d)
if(!deleteData){
print("****************************************************");
print("****************************************************");
print("DEBUG IS ENABLE NO DELETE DATA");
print('to remove DEBUG use --eval "var deleteData=true"')
print("****************************************************");
print("****************************************************");
print("****************************************************");
}//if(!deleteData)
for(name in db.getMongo().getDBNames()){
var dbName = db.getMongo().getDBNames()[name];
if(dbName.indexOf(dbNameIndexOf) === -1){
print("db " + dbName + " is not a " + dbNameIndexOf);
continue;
}//if(dbName.indexOf(dbNameIndexOf) === -1)
var dbObj = db.getSisterDB(dbName);
for(var colName in dbObj.getCollectionNames()){
var collectionName = dbObj.getCollectionNames()[colName];
if(excludeCollection.indexOf(collectionName) > -1)
continue;
print("DB Name => " + dbName);
print("collection Name => " + collectionName);
print("start analyze...");
var coll = dbObj[collectionName];
var maxminDateAggregate = coll.aggregate([ {$group: {_id:"1",max:{$max:"$ts"}, min:{$min:"$ts"} } } ]);
print_debug("DEBUG",maxminDateAggregate);
var dateMin = maxminDateAggregate.toArray()[0].min;
var dateMax = maxminDateAggregate.toArray()[0].max;
print_debug("DEBUG dateMax",dateMax);
var deleteFrom = new Date();
deleteFrom.setDate(dateMax.getDate()-beforePurgeDay);
print_debug("DEBUG deleteFrom ",deleteFrom);
print("Max Date in log => " + convertDate(dateMax));
print("Delete all before day: -" + beforePurgeDay);
print("Delete ==> from " + convertDate(dateMin) + " to " + convertDate(deleteFrom));
var query = {"ts" : {"$lte" : deleteFrom }};
print_debug("DEBUG query to delete: ",query);
var count = coll.count(query);
print("Tot to delete => " + count);
if(deleteData){
var start = new Date().getTime();
print("running...");
var result = coll.remove(query);
print("RESULT ==>", result);
var end = new Date().getTime();
var time = end - start;
print("Tot time => " + time);
}//if(deleteData)
}//for(var colName in dbObj.getCollectionNames())
}//for(name in db.getMongo().getDBNames())

martedì 2 febbraio 2016

MongoDB - Migrazione da ReplicaSet a Singolo Nodo

Alle volte capita di dover demolire una replica e riportare i dati su un singolo nodo del MongoDB.

ecco la procedura testata su MongoDB 3.0.8



mongoserver:PRIMARY> rs.status();
{
"set" : "mongoserver",
"date" : ISODate("2016-02-02T10:47:07.510Z"),
"myState" : 1,
"members" : [
{
"_id" : 3,
"name" : "192.168.1.10:37017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1195281,
"optime" : Timestamp(1454409817, 1),
"optimeDate" : ISODate("2016-02-02T10:43:37Z"),
"lastHeartbeat" : ISODate("2016-02-02T10:47:07.230Z"),
"lastHeartbeatRecv" : ISODate("2016-02-02T10:47:07.194Z"),
"pingMs" : 0,
"syncingTo" : "192.168.1.10:27017",
"configVersion" : 16
},
{
"_id" : 4,
"name" : "192.168.1.10:47017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 1195281,
"lastHeartbeat" : ISODate("2016-02-02T10:47:06.225Z"),
"lastHeartbeatRecv" : ISODate("2016-02-02T10:47:07.238Z"),
"pingMs" : 0,
"configVersion" : 16
},
{
"_id" : 5,
"name" : "192.168.1.10:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1195286,
"optime" : Timestamp(1454409817, 1),
"optimeDate" : ISODate("2016-02-02T10:43:37Z"),
"electionTime" : Timestamp(1453214750, 1),
"electionDate" : ISODate("2016-01-19T14:45:50Z"),
"configVersion" : 16,
"self" : true
}
],
"ok" : 1
}
##Remove Secondary
mongoserver:PRIMARY> rs.remove("192.168.1.10:37017")
{ "ok" : 1 }
mongoserver:PRIMARY> rs.remove("192.168.1.10:47017")
{ "ok" : 1 }
mongoserver:PRIMARY> rs.status();
{
"set" : "mongoserver",
"date" : ISODate("2016-02-02T10:48:23.214Z"),
"myState" : 1,
"members" : [
{
"_id" : 5,
"name" : "192.168.1.10:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1195362,
"optime" : Timestamp(1454410079, 1),
"optimeDate" : ISODate("2016-02-02T10:47:59Z"),
"electionTime" : Timestamp(1453214750, 1),
"electionDate" : ISODate("2016-01-19T14:45:50Z"),
"configVersion" : 18,
"self" : true
}
],
"ok" : 1
}
stop all mongo service
/etc/init.d/mongod1 stop
/etc/init.d/mongod2 stop
/etc/init.d/mongod3 stop
comment replicaset info in /etc/mongod1.conf
#replication:
# replSetName: mongoserver
restart single node
/etc/init.d/mongod_single start
connect to mongo
> use local
switched to db local
> db.dropDatabase();
{ "dropped" : "local", "ok" : 1 }
restart mongo
/etc/init.d/mongod_single stop
/etc/init.d/mongod_single start
##Delete old folder data