Notes On Erlang (2)

How To Be Able To Write Erlang In 15 Minutes

AuthorSebastien Pierre <sebastien@ivy.fr>
Date15-Jul-2007

Concurrency

Distribution

NODE@HOST

Mnesia

Mnesia is the (distributed) database system that comes with Erlang. It has all the properties that you would expect from a RDBMS, plus much more. It is very appealing for today's web apps (and there are some examples).

Mnesia allows you to design a relation DB, where the values can be any Erlang value, which make it close to an object persistence DB.

The first step is to create records representing your database tables in an Erlang header file (delicious.hrl):

-record(bookmark,{id,url,title,description,date}).
-record(user,{id,login}).

this creates records bookmark and user that will be used to create tables in the DB. The first field will be used as a key for the table.

We can now define a module (delicious.erl) that creates the tables in Mnesia:

-module(delicious).
-include("delicious.hrl").
-export([init/0]).
>
init() ->
    mnesia:create_table(bookmark,[{attributes,record_info(fields,bookmarks)}]),
    mnesia:create_table(user,[{attributes,record_info(fields,user)}])
.

Mnesia supports different kinds of table:

  • bag is a table where you can have multiple values with the same key
  • set (the default), when you want only one value for the same key
  • ordered_set when the set preserves ordering

And mnesia tables can be stored in different ways

  • In ram (ram_copies)
  • On disk and ram (disc_copies)
  • On disk only (disc_only_copies)

Mnesia lets you create access data by using transactions (so you have an ACID DB)

create_bookmark(URL, Title, Description) ->
	T = fun() ->
		B = #bookmark{url=Url,title=Title,description=Description},
		mnesia:write(B)
	end,
	mnesia:transaction(T).
Important note
The Fun you give to transaction must have no side-effect (no io, either console, screen, file, network, IPC, etc). If it is not the case, you run the risk of locking the whole system (!!).

You can do many operations (create, modify, delete), as well as querying records, updating them in batch and. I think it's important to read the Mnesia user's guide section 4 (on transaction), so that you have a good idea of what's happening.

When creating a new entry in the DB you'll probably go through the question of what to use as a key (either auto-incremental or GID). Here is how to easily generate a GID:

Id = {node(),erlang:now()}

but you can also use an auto-incremental counter:

Id = mnesia:dirty_update_counter({bookmark,id},1)

Now start mnesia and init the database we've created:

mnesia:start().
delicious:init().

Good to know

erl -mnesia dir '"/path/to/db" to start Mnesia with the DB at the given location

  • -
Mnesia User's Guide, version 4.3.5 (Jul '07) web book