๐ MongoDB Debugging & Troubleshooting Guide
A comprehensive guide for diagnosing and troubleshooting MongoDB database issues.
๐ Table of Contents
๐ Connection & Status
Connect to MongoDB
# Connect to local instance
mongosh
# Connect to remote instance
mongosh "mongodb://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<DATABASE>"
# Connect with authentication database
mongosh --host <HOST> --port 27017 -u <USERNAME> -p <PASSWORD> --authenticationDatabase admin
Check MongoDB Version
db.version()
// Or more detailed
db.serverStatus().version
Check Server Status
// Comprehensive server status
db.serverStatus()
// Specific sections
db.serverStatus().connections
db.serverStatus().network
db.serverStatus().opcounters
db.serverStatus().mem
Check Current Operations
// All current operations
db.currentOp()
// Only active operations
db.currentOp({ "active": true })
// Long-running queries (> 5 seconds)
db.currentOp({
"active": true,
"secs_running": { "$gt": 5 }
})
๐ Database & Collection Info
List All Databases
show dbs
// Or with detailed info
db.adminCommand({ listDatabases: 1 })
// Databases with sizes
db.adminCommand({ listDatabases: 1, nameOnly: false })
Database Statistics
// Current database
db.stats()
// Specific database
use <DATABASE_NAME>
db.stats()
// Human-readable sizes
db.stats(1024*1024) // In MB
List All Collections
show collections
// Or with details
db.getCollectionNames()
// Collection info with stats
db.getCollectionInfos()
Collection Statistics
// Basic stats
db.<COLLECTION_NAME>.stats()
// Detailed stats with index details
db.<COLLECTION_NAME>.stats({ indexDetails: true })
// Size information
db.<COLLECTION_NAME>.totalSize()
db.<COLLECTION_NAME>.storageSize()
db.<COLLECTION_NAME>.totalIndexSize()
Document Count
// Fast count (uses metadata)
db.<COLLECTION_NAME>.estimatedDocumentCount()
// Accurate count (slower)
db.<COLLECTION_NAME>.countDocuments()
// Count with filter
db.<COLLECTION_NAME>.countDocuments({ status: "active" })
Check Database Profiler
// Enable profiler (level 2 = all operations)
db.setProfilingLevel(2)
// Level 1 = slow operations only (> 100ms)
db.setProfilingLevel(1, { slowms: 100 })
// Check current profiling level
db.getProfilingStatus()
// View profiler data
db.system.profile.find().limit(10).sort({ ts: -1 }).pretty()
// Find slow queries
db.system.profile.find({
millis: { $gt: 1000 }
}).sort({ ts: -1 }).pretty()
// Disable profiler
db.setProfilingLevel(0)
Monitor Database Operations
// Real-time stats
db.serverStatus().opcounters
// Monitor specific operations
db.currentOp({
"$or": [
{ "op": "query" },
{ "op": "getmore" },
{ "op": "insert" },
{ "op": "update" },
{ "op": "remove" }
]
})
Memory Usage
// Memory statistics
db.serverStatus().mem
// WiredTiger cache statistics
db.serverStatus().wiredTiger.cache
// Connection statistics
db.serverStatus().connections
Check Lock Statistics
// Global lock information
db.serverStatus().globalLock
// Current locks
db.currentOp({ "waitingForLock": true })
// Lock statistics
db.serverStatus().locks
๐ Replication & Replica Sets
Replica Set Status
// Full replica set status
rs.status()
// Replica set configuration
rs.conf()
// Check if node is primary
db.isMaster()
// Simpler primary check
rs.isMaster()
Replication Lag
// Check replication lag for all members
rs.printReplicationInfo()
// Detailed secondary status
rs.printSecondaryReplicationInfo()
// Check oplog window
db.getReplicationInfo()
Monitor Oplog
// Switch to local database
use local
// Oplog statistics
db.oplog.rs.stats()
// First and last oplog entries
db.oplog.rs.find().sort({ $natural: 1 }).limit(1).pretty()
db.oplog.rs.find().sort({ $natural: -1 }).limit(1).pretty()
// Oplog size
db.oplog.rs.stats().maxSize / (1024*1024*1024) // In GB
Replica Set Management
// Add member to replica set
rs.add("<HOSTNAME>:<PORT>")
// Remove member
rs.remove("<HOSTNAME>:<PORT>")
// Step down primary
rs.stepDown(60) // seconds
// Force reconfiguration
rs.reconfig(<NEW_CONFIG>, { force: true })
๐ Query Analysis
Explain Query Plan
// Explain query execution
db.<COLLECTION_NAME>.find({ field: value }).explain("executionStats")
// Detailed explanation
db.<COLLECTION_NAME>.find({ field: value }).explain("allPlansExecution")
// Check if index is used
db.<COLLECTION_NAME>.find({ field: value }).explain("queryPlanner")
Find Slow Queries
// From profiler
db.system.profile.find({
millis: { $gt: 100 }
}).sort({ millis: -1 }).limit(10).pretty()
// Queries with collection scans (COLLSCAN)
db.system.profile.find({
"planSummary": { $eq: "COLLSCAN" }
}).sort({ millis: -1 }).pretty()
// Time query execution
var start = new Date()
db.<COLLECTION_NAME>.find({ field: value }).toArray()
var end = new Date()
print("Query took: " + (end - start) + "ms")
// Or use explain with execution stats
db.<COLLECTION_NAME>.find({ field: value })
.explain("executionStats").executionStats.executionTimeMillis
๐ Indexing
List All Indexes
// For a collection
db.<COLLECTION_NAME>.getIndexes()
// All indexes in database
db.getCollectionNames().forEach(function(collection) {
print("\n=== Indexes for: " + collection + " ===");
printjson(db[collection].getIndexes());
});
Create Indexes
// Single field index
db.<COLLECTION_NAME>.createIndex({ field: 1 })
// Compound index
db.<COLLECTION_NAME>.createIndex({ field1: 1, field2: -1 })
// Text index
db.<COLLECTION_NAME>.createIndex({ field: "text" })
// Create index in background
db.<COLLECTION_NAME>.createIndex({ field: 1 }, { background: true })
// Unique index
db.<COLLECTION_NAME>.createIndex({ field: 1 }, { unique: true })
// TTL index (auto-delete after time)
db.<COLLECTION_NAME>.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
Index Usage Statistics
// Index stats
db.<COLLECTION_NAME>.aggregate([
{ $indexStats: {} }
])
// Find unused indexes
db.<COLLECTION_NAME>.aggregate([
{ $indexStats: {} },
{ $match: { "accesses.ops": 0 } }
])
Drop Indexes
// Drop specific index
db.<COLLECTION_NAME>.dropIndex("index_name")
// Drop all indexes except _id
db.<COLLECTION_NAME>.dropIndexes()
// Drop specific index by specification
db.<COLLECTION_NAME>.dropIndex({ field: 1 })
๐๏ธ Sharding
Sharding Status
// Overall sharding status
sh.status()
// Check if sharding is enabled for database
use <DATABASE_NAME>
db.stats()
// List all shards
use config
db.shards.find().pretty()
Shard Distribution
// Check chunk distribution
use config
db.chunks.aggregate([
{ $group: { _id: "$shard", count: { $sum: 1 } } }
])
// Check collection sharding info
db.<COLLECTION_NAME>.getShardDistribution()
Enable Sharding
// Enable sharding for database
sh.enableSharding("<DATABASE_NAME>")
// Shard a collection
sh.shardCollection("<DATABASE_NAME>.<COLLECTION_NAME>", { shardKey: 1 })
Balancer Status
// Check balancer status
sh.getBalancerState()
// Start/stop balancer
sh.startBalancer()
sh.stopBalancer()
// Check if balancer is running
sh.isBalancerRunning()
๐ ๏ธ Operations & Maintenance
Kill Operation
// Find operation ID
db.currentOp()
// Kill specific operation
db.killOp(<OPERATION_ID>)
Compact Collection
// Reclaim disk space
db.runCommand({ compact: "<COLLECTION_NAME>" })
// Compact with force
db.runCommand({ compact: "<COLLECTION_NAME>", force: true })
Validate Collection
// Validate collection integrity
db.<COLLECTION_NAME>.validate()
// Full validation (slower but thorough)
db.<COLLECTION_NAME>.validate({ full: true })
Repair Database
# Stop MongoDB and run repair
mongod --repair --dbpath /path/to/data
# Or from inside MongoDB (requires space)
db.repairDatabase()
Backup & Restore
# Backup entire database
mongodump --host <HOST> --port <PORT> -u <USERNAME> -p <PASSWORD> --out /backup/path
# Backup specific database
mongodump --host <HOST> --port <PORT> -u <USERNAME> -p <PASSWORD> -d <DATABASE> --out /backup/path
# Backup specific collection
mongodump --host <HOST> --port <PORT> -u <USERNAME> -p <PASSWORD> -d <DATABASE> -c <COLLECTION> --out /backup/path
# Restore database
mongorestore --host <HOST> --port <PORT> -u <USERNAME> -p <PASSWORD> /backup/path
# Restore specific database
mongorestore --host <HOST> --port <PORT> -u <USERNAME> -p <PASSWORD> -d <DATABASE> /backup/path/<DATABASE>
User Management
// Create user
use admin
db.createUser({
user: "<USERNAME>",
pwd: "<PASSWORD>",
roles: [ { role: "readWrite", db: "<DATABASE>" } ]
})
// List all users
use admin
db.system.users.find().pretty()
// Drop user
db.dropUser("<USERNAME>")
// Change user password
db.changeUserPassword("<USERNAME>", "<NEW_PASSWORD>")
๐ Monitoring & Metrics
Connection Statistics
// Current connections
db.serverStatus().connections
// Connection pool stats
db.serverStatus().network
Operation Counters
// Operations per second
db.serverStatus().opcounters
// Network metrics
db.serverStatus().network
Storage Engine Statistics (WiredTiger)
// Cache statistics
db.serverStatus().wiredTiger.cache
// Transaction statistics
db.serverStatus().wiredTiger.transaction
// Cursor statistics
db.serverStatus().wiredTiger.cursor
Collection Scan Statistics
// Find collections with high scan ratios
db.getCollectionNames().forEach(function(collection) {
var stats = db[collection].stats();
if (stats.count > 0) {
print(collection + ": " + stats.totalIndexSize + " index size, " +
stats.size + " collection size");
}
});
๐จ Common Issues & Solutions
Issue: High Memory Usage
// Check cache usage
db.serverStatus().wiredTiger.cache
// Solution: Adjust cache size in mongod.conf
// storage.wiredTiger.engineConfig.cacheSizeGB
Issue: Slow Queries
// Enable profiler
db.setProfilingLevel(1, { slowms: 100 })
// Check slow queries
db.system.profile.find({ millis: { $gt: 100 } }).sort({ ts: -1 })
// Solutions:
// 1. Add appropriate indexes
// 2. Optimize query patterns
// 3. Use projection to limit fields
Issue: Connection Limit Reached
// Check current connections
db.serverStatus().connections
// Kill idle connections
db.currentOp({ "active": false }).inprog.forEach(function(op) {
if (op.secs_running > 300) { // 5 minutes
db.killOp(op.opid);
}
});
// Solution: Increase maxIncomingConnections in mongod.conf
Issue: Replica Lag
// Check lag
rs.printSecondaryReplicationInfo()
// Solutions:
// 1. Check network latency
// 2. Increase oplog size
// 3. Check secondary hardware resources
// 4. Reduce write load on primary
Issue: Lock Contention
// Check current locks
db.currentOp({ "waitingForLock": true })
// Solutions:
// 1. Optimize queries
// 2. Use appropriate indexes
// 3. Batch writes
// 4. Consider sharding
๐ง Configuration Check
View Current Configuration
// Get all parameters
db.adminCommand({ getParameter: '*' })
// Specific parameters
db.adminCommand({ getParameter: 1, maxConnections: 1 })
Check Data Directory
๐ Best Practices
- Always use indexes for frequently queried fields
- Monitor replica lag in production environments
- Enable profiling only when debugging (impacts performance)
- Regular backups using mongodump or file system snapshots
- Use projection to limit returned fields
- Batch operations when possible to reduce network overhead
- Monitor oplog size to ensure sufficient replication window
- Use connection pooling in applications
- Set appropriate TTL indexes for time-series data
- Regular compaction to reclaim disk space
- MongoDB Compass - GUI for MongoDB
- mongostat - Real-time statistics
- mongotop - Track read/write activity
- MongoDB Atlas - Cloud monitoring
- Percona Monitoring and Management (PMM) - Advanced monitoring
- mongo-hacker - Enhanced shell with colors and formatting
๐ Additional Resources
Check Logs
# Typical log location
tail -f /var/log/mongodb/mongod.log
# Search for errors
grep -i error /var/log/mongodb/mongod.log
# Search for slow queries
grep -i "slow query" /var/log/mongodb/mongod.log
System Resource Usage
# Check MongoDB process
ps aux | grep mongod
# Monitor with top
top -p $(pgrep mongod)
# Check disk usage
df -h /path/to/mongodb/data
# Check I/O statistics
iostat -x 2
โ ๏ธ Security Notes
- Never expose MongoDB to the internet without authentication
- Always use strong passwords
- Enable SSL/TLS for production deployments
- Regularly update MongoDB to latest stable version
- Use role-based access control (RBAC)
- Audit database access regularly