Database Backup, Backup Automation, and Restore in MongoDB

Backup a single database using mongodump

In many examples of how to backup a MongoDB database found online, those examples don't use authentication. So if you have enabled auth on your MongoDB instance you will need to do one of two things when backing up a database. Either you will specify a user from the target database you are backing up and then authenticate with that or else you'll want to use an admin or backup account and authenticate with that instead. Notice I am calling out the admin database as my authentication database. The user here would be some kind of server scoped admin with permissions to backup all database and they would reside in the admin database. This way especially makes sense when we get in to automating the backup routine for all databases in our instance. If you have not enabled auth in your instance, you can exclude the user, password, and authentication database but I would strongly suggest you look in to setting up authentication.

 Without compression:

 mongodump -h myMongoHost:27017 –d myDatabase -u myAdminUser -p myPassword --authenticationDatabase admin -o /data/backups/MyDatabaseBackup

With compression:

 mongodump -h myMongoHost:27017 -d DatabaseName -u AdminUser -p password --authenticationDatabase admin --gzip --archive=/data/backups/MyDatabaseNameBackup

Here are the options we used:

-h is the host name
-u is the username you want to login in with
-p is the password
-d is the database you want to backup
-o is the location you want to backup to ( without compression )

Compression options:

--gzip tells the backup to use compression
--archive is the location of the compressed backup

* If you exclude the -d flag, mongodump will back up all databases.

Automating MongoDB Backups

In order to automate the backup of databases in MongoDB, we'll need to create a shell script that can be run in a Linux cron job. So pick a directory and let's create the script. You can use whatever file editor you choose, I typically use vim. Modify the contents below then copy and paste them to the new file you created.

# Use mongodump to backup all databases in a Mongo instance
# Variables

TIMESTAMP=`date +%F-%H%M`

#Backup commands

$MONGODUMP -h $MONGOHOST:$MONGOPORT -d StackExchange -u myAdmin -p myPassword --authenticationDatabase admin --gzip --archive=/data/backups/ StackExchange$TIMESTAMP

$MONGODUMP -h $MONGOHOST:$MONGOPORT -d AdventureWorks -u mongoadmin -p myPassword --authenticationDatabase admin --gzip --archive=/data/backups/ AdventureWorks$TIMESTAMP

$MONGODUMP -h $MONGOHOST:$MONGOPORT -d Census -u myAdmin -p myPassword --authenticationDatabase admin --gzip --archive=/data/backups/ Census$TIMESTAMP

# Begin file cleanup, older than 3 days

find /data/backups -type f -mtime +2 -delete

The variables are things like your mongo server name, port, directory, etc. The backup commands apply the variables and there is a single command for each database we want to backup, in this example we have three databases. Finally, we have a cleanup command that will delete backup files older than 3 days. Once you have modified the file and saved it, next we need to give execute permission to the script we just created. We can do this using chmod. Chmod allows us to change the access permissions to file system objects. Modify this according to where you created your file.

chmod +x /home/YourDirectory/

Next we need to create a cronjob to run the script nightly. Open the crontab file as the root user, we can sudo with the -u flag to access as root.

sudo crontab -e -u root

Following the last line of comments in the crontab file, add the following line to run your script every day at 3:25 PM. You can modify the number preceding the script to your preferred backup time.

25 15 * * * /home/YourDirectory/

These fields follow an order of minute, hour, day of month, month, day of week. An asterisk means it’ll run on every division of the interval. So our job is set to run daily at 3:25 PM.

If you want to check on the status of a cron job, you can use the following:

sudo grep CRON /var/log/syslog

A quick note on cron permissions-- If you setup the cronjob under a user other than root, you might have problems running the job, in which case you need to grant explicit permissions to the user. I would recommend you setup cronjobs as the root user.

Restore a single database using mongorestore without compression

Like we explained in the database backup section of this guide, when restoring a database using mongorestore you must use an account that has permissions in the backed up database or else you need to specify the --authorizationDatabase option. The authorization database is the database you authenticate with. In most cases this would be the admin database, using an account that has admin permissions across the entire environment.

Backup from Server (A) and restore to Server(B), the database does not exist on Server (B):

mongorestore --host servername:27017 -u myAdminLogin -p myPassword --authenticationDatabase admin -d myDatabase /data/backups/MyDatabaseNameBackup

Backup from Server (A) and restore to Server (B), the database already exists on Server (B) so we want to replace it. All we need to do is follow the steps from the previous restore and this time include the --drop flag. 

mongorestore --host servername:27017 -u myAdminLogin -p myPassword --authenticationDatabase admin --drop -d myDatabase /data/backups/MyDatabaseNameBackup

Restoring a compressed backup using mongorestore

It's important to note, you cannot restore a compressed database to a database name different from the original database you backed up unless you are running ver. 3.4 +  and use the new ns options. If you are not on 3.4 + you can still restore a compressed backup, but only to the same name of the database you backed up. Be careful not to overwrite the existing database when performing a restore from a compressed backup.

mongorestore --host servername:27017 -u mongoadmin -p mypassword --authenticationDatabase admin --gzip --archive=/data/backups/MyDatabaseNameBackup

Restoring a compressed backup to a new database name (MongoDB 3.4 and higher):

mongorestore --host servername:27017 -u mongoadmin -p mypassword --authenticationDatabase admin --gzip --archive=/data/backups/MyDatabaseNameBackup --nsInclude 'DatabaseName.*' --nsFrom 'DatabaseName.*' --nsTo 'NewDatabaseName.*'

nsInclude, nsFrom and nsTo are new to MongoDB 3.4. The * is a wildcard for all objects in the target namespace. This restores a database named "myDatabase" to a database named "myNewDatabase".