Quick Tip: Copy DBs Between Servers

in Administration, Quick Tip

Inspired by this Stackoverflow question I thought it would be worth while to post this quick tip …

If you ever need to copy (or “clone”) a MongoDB databse between two MongoDB servers its as easy as running the copyDatabase() command.

First, change into your admin db …

Then, run copyDatabase() supplying the needed information, the “from_db” (the database to copy) the “to_db” and the host name of the database you are copying …

> use admin;
> db.copyDatabase(…);

You’ll need to run the copyDatabase() command on the sever you want to “copy” the database to, aka the “destantion” server …

> db.copyDatabase(from_db, to_db, from_host);

If you are running MongoDB with accounts/password via –auth you’ll need to add that info on there too …

> db.copyDatabase(from_db, to_db, from_host, username, password);

A simple example for a database named “weyoun” on a host called “delta.quad.com” would be like so …

> db.copyDatabase('weyoun', 'weyoun', 'delta.quad.com');

There ya go, you should be good to go copying your MongoDB database!

 

5 Comments

Sorry It Has Been So Quiet …

in Announcements

Dear Readers,

Sorry it’s been so quiet lately … thing is LearnMongo is moving!

Well not moving sites or anything … but I’m moving … to the sunny North West (at least that’s what my new boss keeps telling me?) …

Seattle Bound (wait that sounds wrong)

Once all the moving stuff is taken care of LearnMongo will be back to regular posts (staring in March.)

I’m sure I’ll have plenty of coffee to fuel some awesome Mongoness.

Thanks for your support so far, and I’m looking forward to lots more Mongo in 2011.

~ Justin

3 Comments

MongoLA 2011 Talk Slides

in MongoLA

MongoLA 2011

Here are the slides from my talk at MongoLA last week, hopefully the audio will be up soon (I will post it here.)

There is a nice write up of the event here… thanks to everyone that came!

Beyond Logging

Using MongoDB to Power a Private Social Network

(Oh, and log millions of e-mails too.)

photo
photo
photo
photo

1 Comment

Compacting MongoDB Data Files

in Administration, Stackoverflow

StackOverflow Anwser Series

This is a new “concept” post based on StackOverflow Questions/Answers.

Feel free to comment below if this format is helpful & informative!

Overview

This Answer covers the following MongoDB topics:

  • Data Files
  • Compacting Data Files
  • The db.repairDatabase(); command
  • Capped Collections
  • Server-side Javascript

Question

StackOverflow Link

Is there a way to auto compact MongoDB Data Files?

The mongodb documentation says that:

To compact this space, run db.repairDatabase() from the mongo shell (note this operation will block and is slow).

I’m wondering how to make the mongodb free deleted disk space automatically?

Answer

StackOverflow Link

In general if you don’t need to shrink your datafiles you shouldn’t shrink them at all. This is because “growing” your datafiles on disk is a fairly expensive operation and the more space that MongoDB can allocate in datafiles the less fragmentation you will have.

Also doing any sort of “shrink” will likely be a rather expensive operation and will likely lock your database while it’s running!

So, you should try avoid shrinking and provide as much disk-space as possible for the database.

However if you must shrink the database you should keep two things in mind.

  • MongoDB grows it’s data files by doubling so the datafiles may be 64MB, then 128MB, etc up to 2GB (at which point it stops doubling to keep files until 2GB.)
  • As with most any database … to do operations like shrinking you’ll need to schedule a separate job to do so, there is no “autoshrink” in MongoDB. In fact of the major noSQL databases (hate that name) only Riak will autoshrink. So, you’ll need to create a job using your OS’s scheduler to run a shrink. You could use an bash script, or have a job run a php script, etc.

Server-side Javascript

You can use server-side Javascript to do the shrink and run that JS via mongo’s shell on a regular bases via a job (like cron or the windows scheduling service) …

Assuming a collection called foo you would save the javascript below into a file called bar.js and run …

$ mongo foo bar.js

The javascript file would look something like …

bar.js

// 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));

This will run and return something like …

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

Run this on a schedule (during non-peak hours) and you are good to go.

Capped Collections

However there is one other option, capped collections.

Capped collections are fixed sized collections that have a very high performance auto-FIFO age-out feature (age out is based on insertion order). They are a bit like the “RRD” concept if you are familiar with that.

In addition, capped collections automatically, with high performance, maintain insertion order for the objects in the collection; this is very powerful for certain use cases such as logging.

Basically you can limit the size of (or number of documents in ) a collection to say .. 20GB and once that limit is reached MongoDB will start to throw out the oldest records and replace them with newer entries as they come in.

This is a great way to keep a large amount of data, discarding the older data as time goes by and keeping the same amount of disk-space used.

5 Comments

Quick Tip: Using Users in MongoDB

in Administration, Quick Tip

By default a MongoDB install does not use a username/password combination to access the database.

No Password, But Why?

This is down to the design philosophy of MongoDB which is to push much of the “logic” to the application level and keep the database doing what databases do best! Hence,  given the way that MongoDB is normally used it’s generally not necessary.

In a SQL environment you might have multiple users with multiple groups and schemas to lock down different levels of the database, tables, views, stored procedures, etc. …

The idea of this is of course to 1) protect data from unauthorized modification or deletion as well as 2)  limiting the tug ‘o war between users by clearly defining their rights.

So, you can give the accounting department different privileges then the marketing department or given root access to the developers (of course.)

Conversely MongoDB’s design philosophy would pass these (generally) over to the application itself to handle.

I Don’t Care, I Still Want Passwords!

No worries, if the idea of no users/passwords keeps you up at nights you can still have them!

MongoDB (currently) supports users on the database level with both “read/write” and “read only” options.

You can see all the users in a database in the system.users collection …

> use mydatabase
> db.system.users.find()

Creating MongoDB Users

To adding a new user is fairly straight forward …

Read/Write User

$ ./mongo
> use mydatabase
> db.addUser("admin", "Sup3rG00dP@azzword")

This creates a read/write user for the database mydatabase (you can choose any username you wish.)

This user will be “good for” this database alone.

Read Only User

> db.addUser("web", "prettyGoodPass", true)

The “true” parameter there makes the user read only (great for parts of the application code that you want to make sure never accidentally preform a write operation.)

Using A User: Authenticate

To “login” as a user you’ll need to authenticate, simply use …

> db.auth("admin", "Sup3rG00dP@azzword")

You can also authenticate via the command line using the mongo parameters below …

  -u [ --username ] arg username for authentication
  -p [ --password ] arg password for authentication

Changing Passwords

To change the password simply run the addUser command again with a new password.

> db.addUser("web", "wayGooderPass", true)

Delete a User

To remove a user you need to remove the corresponding document for that user in the system.users collection.

> db.system.users.remove({"user" : "web"});

Set MongoDB to Force Authentication

To force MongoDB to use authentication you’ll need to add the –auth parameter to MongoDB at startup (so you would need to restart.)

If you are using an unauthorized user you’ll get an error something like …

error: { “$err” : “unauthorized for db [mydatabase] lock type: -1 ” }

If you have a read only user and attempt a write option you’ll simply get back …

unauthorized

Lastly, if you try to use a user that doesn’t have read/write privlages on the admin database …

So, if you try to do something like list the avaible database on the server ( > show dbs ) you’ll get error too and you’ll need to make sure you switch to an account with read/write privlages in admin.

4 Comments