MongoDB: Logical Backup and Restore

MongoDB: Logical Backup and Restore

Table of Contents



1. What Is a Logical Backup?

A logical backup reads your documents through the database and saves them, with the index definitions, in a format MongoDB can read back. It is not a copy of the files on disk. You use it to move data, restore one collection, or recover from accidental deletes.

MongoDBOracle
Tool: mongodump (backup) and mongorestore (restore)Tool: expdp (Data Pump export) and impdp (import)
Format: BSON files (binary JSON) + index definitions as JSONFormat: proprietary dump file (.dmp)
Runs on the client side and reads data over the networkRuns on the server side and writes to a directory object
Works on: standalone, replica set, sharded cluster (a sharded cluster needs a different tool for a consistent backup, see below)Works on: any Oracle database
Consistency: --oplog makes a full replica set dump consistent as of the end of the dump. It is not recovery to an arbitrary point in time.Consistency: FLASHBACK_TIME / FLASHBACK_SCN
Users and roles: included in a full dump (the admin database). With --db, add --dumpDbUsersAndRoles.Users, roles and grants: included in full and schema exports

  mongodump --oplog
     |  1. note the oplog position                    (start of dump)
     |  2. read every collection                      --> <coll>.bson + <coll>.metadata.json
     |        (writes keep happening on the server)
     |  3. copy the oplog entries that arrived        --> oplog.bson
     v
  backup folder

  mongorestore --oplogReplay
     |  1. insert the documents                       (normal write path: journal + oplog)
     |  2. rebuild the indexes                        (from metadata.json)
     |  3. replay oplog.bson                          --> data consistent as of END of dump
     v
  restored data

Key points:
• mongodump and mongorestore are separate tools you run from the Linux shell, not from inside mongosh. Install them with the mongodb-database-tools package.
• mongodump never dumps the local database (the oplog lives there).
• Without --oplog, a dump is not consistent across collections, because writes can happen between reading one collection and the next. This is the same issue as expdp without flashback_time.
• The dump reads all data through the WiredTiger cache. On a busy server, dump from a secondary if you can.
• Authentication needs a user with the built-in backup role (dump) and restore role (restore). A restore with --oplogReplay may need more privileges, so many DBAs use a root-level user for restores.

2. Backup (mongodump) — Full, Database, Collection

All commands are run from the Linux shell (not mongosh). Replace host, port, username, and paths with your own.

Password on the command line: --password 'yourpassword' is visible in ps output to other users on the server. The examples below use it for clarity. In real use, leave out --password (you will be prompted) or keep the URI in a protected file and use --config.

Full backup (everything except local)

Backs up all databases and collections, including the admin database, so users and roles are included. Use --oplog on a replica set to make the whole dump consistent as of the end of the dump.


# Full backup of everything on the server
mongodump \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --oplog \
  --out /backup/mongodb/full_$(date +%Y%m%d_%H%M%S)

# Output goes to:
# /backup/mongodb/full_20250115_103000/
#   ├── admin/                       (users and roles are here)
#   │   ├── system.users.bson
#   │   ├── system.roles.bson
#   │   └── system.version.bson
#   ├── myFirstDB/
#   │   ├── students.bson
#   │   ├── students.metadata.json
#   │   ├── orders.bson
#   │   └── orders.metadata.json
#   ├── shop/
#   │   ├── accounts.bson
#   │   └── accounts.metadata.json
#   └── oplog.bson                   (only with --oplog; one file in the top folder)
#
# The local database is never dumped.

About --oplog:
• It works only for a full dump of a replica set. You cannot combine it with --db or --collection, and it does not work on a standalone server.
• Use --oplog on dump and --oplogReplay on restore. They go as a pair.
• Sharded clusters: running mongodump --oplog on each shard separately does not give a consistent cluster backup. Use coordinated snapshots, PBM, Ops Manager, Cloud Manager or Atlas.

Database backup (one database only)

No --oplog here, because it cannot be used with --db.


# Backup only the myFirstDB database
mongodump \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --db myFirstDB \
  --out /backup/mongodb/db_myFirstDB_$(date +%Y%m%d_%H%M%S)

# Output:
# /backup/mongodb/db_myFirstDB_20250115_103000/
#   └── myFirstDB/
#       ├── students.bson
#       ├── students.metadata.json
#       ├── orders.bson
#       └── orders.metadata.json

# To also save the users and roles that belong to this database:
#   add  --dumpDbUsersAndRoles

Collection backup (one collection only)


# Backup only the students collection
mongodump \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --db myFirstDB \
  --collection students \
  --out /backup/mongodb/coll_students_$(date +%Y%m%d_%H%M%S)

# Output:
# /backup/mongodb/coll_students_20250115_103000/
#   └── myFirstDB/
#       ├── students.bson
#       └── students.metadata.json

Useful options

OptionWhat it does
--oplogCaptures the oplog so the dump is consistent as of the moment it finished. Full dump of a replica set only.
--dumpDbUsersAndRolesWith --db, also dumps the users and roles of that database.
--gzipCompresses the output files.
--archive=file.gzWrites everything to a single file instead of a directory. Cannot be used together with --out.
--query '{...}'Backs up only matching documents. Needs --db and --collection. Dates and ObjectIds need extended JSON, for example {"$date": "..."}.
--excludeCollection=nameSkips a collection (can be used multiple times).
--readPreference=secondaryReads from a secondary to avoid load on the primary (replica set only).
--numParallelCollections=4Dumps 4 collections at the same time (4 is the default).

Users and roles, in one place:
• Full dump (no --db): the admin database is included, so users and roles are in the backup, and mongorestore restores them.
• --db dump: users and roles are not included unless you add --dumpDbUsersAndRoles.
• Collection dump: no users or roles.

3. Restore (mongorestore) — Full, Database, Collection

Default behaviour: mongorestore only inserts. If a document with the same _id already exists, it is reported as a duplicate key error and skipped. Existing documents are not overwritten. Add --drop if you want each collection replaced.

Full restore (everything)


# Restore everything from a full backup
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --oplogReplay \
  /backup/mongodb/full_20250115_103000

# --oplogReplay replays oplog.bson to bring the data
# to the point when the dump finished.
# Only use it if the backup was made with --oplog.

To replace what is already there:


mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --drop \
  --oplogReplay \
  /backup/mongodb/full_20250115_103000

# --drop removes each collection that is in the backup before restoring it.
# Collections that are NOT in the backup are left alone.

Database restore (one database only)


# Restore only myFirstDB from a FULL backup
# (do not use --oplogReplay when restoring only part of a full dump)
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "myFirstDB.*" \
  /backup/mongodb/full_20250115_103000

# Or restore from a database-level backup:
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  /backup/mongodb/db_myFirstDB_20250115_103000

# If the backup was taken with --dumpDbUsersAndRoles, restore them too:
#   --db myFirstDB --restoreDbUsersAndRoles /backup/mongodb/db_myFirstDB_.../myFirstDB

Collection restore (one collection only)


# Restore only the students collection (from a collection backup)
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "myFirstDB.students" \
  /backup/mongodb/coll_students_20250115_103000

# Or pick one collection out of a full backup:
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "myFirstDB.students" \
  /backup/mongodb/full_20250115_103000

Restore to a different name


# Restore myFirstDB.students as testDB.students_backup
mongorestore \
  --host localhost \
  --port 27017 \
  --username admin \
  --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "myFirstDB.students" \
  --nsFrom "myFirstDB.students" \
  --nsTo "testDB.students_backup" \
  /backup/mongodb/coll_students_20250115_103000

Useful options

OptionWhat it does
--dropDrops each collection that is in the backup before restoring it. Use with care.
--oplogReplayReplays oplog.bson from a dump made with --oplog. Use it only for a full restore.
--nsInclude / --nsExcludeRestores only (or skips) matching namespaces, for example "testdb.*" or "testdb.logs".
--nsFrom / --nsToRenames databases or collections during restore. Use together with --nsInclude.
--gzipRestores from compressed files.
--archive=file.gzRestores from a single archive file.
--noIndexRestoreSkips index creation (faster load, build indexes later).
--numParallelCollections=4Restores 4 collections at the same time (4 is the default).

4. Hands-On Practicals

Follow these steps on a test server to see backup and restore in action. Practical 1 assumes a replica set (because of --oplog). On a standalone server, leave out --oplog and --oplogReplay.

Practical 1: Full backup and restore


// Step 1: Create test data in mongosh
use testdb
db.students.insertMany([
  { name: "Ravi", age: 22, grade: "A" },
  { name: "Sita", age: 21, grade: "B" }
])
db.orders.insertMany([
  { item: "laptop", qty: 1 },
  { item: "phone", qty: 2 }
])
db.students.countDocuments()    // 2
db.orders.countDocuments()      // 2

# Step 2: Backup everything (Linux shell)
mongodump --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --oplog \
  --out /backup/full_test

// Step 3: Drop the database in mongosh (simulate data loss)
use testdb
db.dropDatabase()
db.students.countDocuments()    // 0  (the collection no longer exists)

# Step 4: Restore everything (Linux shell)
mongorestore --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --oplogReplay \
  /backup/full_test

# The admin database is in the backup too. Existing users are skipped
# as duplicates; that is expected.

// Step 5: Verify the data is back in mongosh
use testdb
db.students.countDocuments()    // 2
db.orders.countDocuments()      // 2
db.students.find()
// Data is restored!

Practical 2: Database backup and restore


# Backup only testdb
mongodump --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --db testdb \
  --out /backup/db_testdb

// Delete one collection
use testdb
db.students.drop()

# Restore testdb
mongorestore --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "testdb.*" \
  /backup/db_testdb

# students is re-created. orders already exists, so its documents
# are reported as duplicate keys and skipped. Add --drop to replace them instead.

// Verify
use testdb
db.students.countDocuments()    // 2
db.orders.countDocuments()      // 2

Practical 3: Collection backup and restore


# Backup only the students collection
mongodump --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --db testdb \
  --collection students \
  --out /backup/coll_students

// Delete one document
use testdb
db.students.deleteOne({ name: "Ravi" })
db.students.countDocuments()    // 1

# Restore only the students collection
mongorestore --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "testdb.students" \
  --drop \
  /backup/coll_students

// Verify
use testdb
db.students.countDocuments()    // 2
db.students.find({ name: "Ravi" })

Try without --drop: run the same restore without --drop. Ravi comes back and Sita is reported as a duplicate key and skipped. This is a handy way to bring back deleted documents without touching the rest.

Practical 4: Restore to a different name


# Restore testdb.students as testdb.students_copy
mongorestore --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --nsInclude "testdb.students" \
  --nsFrom "testdb.students" \
  --nsTo "testdb.students_copy" \
  /backup/coll_students

// Verify both exist
use testdb
db.students.countDocuments()         // 2 (original)
db.students_copy.countDocuments()    // 2 (copy)

Practical 5: Compressed backup and restore


# Backup with compression into one file
mongodump --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --db testdb \
  --gzip \
  --archive=/backup/testdb_$(date +%Y%m%d).gz

# Restore from the archive (use the real file name)
mongorestore --host localhost --port 27017 \
  --username admin --password 'yourpassword' \
  --authenticationDatabase admin \
  --gzip \
  --archive=/backup/testdb_20250115.gz \
  --drop

5. Oracle vs MongoDB Comparison

TaskMongoDBOracle
Full backupmongodump --out /backup/fullexpdp full=y directory=backup dumpfile=full.dmp
Database (schema) backupmongodump --db myFirstDBexpdp schemas=HR directory=backup dumpfile=hr.dmp
Table (collection) backupmongodump --db myFirstDB --collection studentsexpdp tables=HR.EMPLOYEES directory=backup dumpfile=emp.dmp
Consistent backupmongodump --oplog (full dump, replica set only)expdp flashback_time=systimestamp
Full restoremongorestore --oplogReplay /backup/fullimpdp full=y directory=backup dumpfile=full.dmp
Database restoremongorestore --nsInclude "myFirstDB.*" /backup/fullimpdp schemas=HR directory=backup dumpfile=hr.dmp
Table restoremongorestore --nsInclude "myFirstDB.students" /backup/fullimpdp tables=HR.EMPLOYEES directory=backup dumpfile=emp.dmp
Restore to different namemongorestore --nsInclude "db.coll" --nsFrom "db.coll" --nsTo "db.coll_new"impdp remap_table=HR.EMPLOYEES:EMP_NEW
Existing data on restoreDefault: duplicate _id skipped. --drop: collection replaced.table_exists_action=skip|append|truncate|replace
Compress backup--gzip --archive=file.gzcompression=all
Includes users and roles?Full dump: yes (admin database). --db dump: only with --dumpDbUsersAndRoles.Yes (with full=y or schemas=)
Where it runsClient side, over the networkServer side, into a directory object
Output formatBSON files + JSON metadata, or one archiveProprietary .dmp file

Bottom line for Oracle DBAs:
• mongodump / mongorestore are like expdp / impdp.
• Use --oplog for a consistent full dump of a replica set (like FLASHBACK_TIME). It cannot be combined with --db or --collection, and it is not recovery to an arbitrary point in time.
• A full dump includes users and roles. A --db dump needs --dumpDbUsersAndRoles.
• local is never dumped. For sharded clusters, do not rely on per-shard dumps.
• Good for small and medium data and single-collection restores. For large databases, use physical backups.

Caution: Your use of any information or materials on this website is entirely at your own risk. It is provided for educational purposes only. It has been tested internally, however, we do not guarantee that it will work for you. Ensure that you run it in your test environment before using.
Thank you
Rajasekhar Amudala