How to start up mnesia in a cluster?

I am looking into mnesia for the first time and I try to set it up in a cluster managed by libcluster.

I saw that you have to pass a list of cluster nodes to mnesia:create_schema before starting mnesia with mnesia:start. start needs to be called on every node while mnesia:create_schema and mnesia:create_table should only be called on one node. In all tutorials this is done by hand in the shell, but how do I do this automatically on startup in the right way? Currently my nodes are all running the exact same code, so all would create a schema and a table.

Hints are very welcome!

You don’t have to have the list of cluster nodes from the start. You only need one node of the cluster to start. mnesia can increase the cluster at runtime with minimal impact on transactions.

There are typically two ways of doing this:

  1. create dbase upon installation.
  2. create dbase upon startup

I do have a preference for (1). Upon installation we would run a escript or some other script to launch a quasi BEAM node to create the dbase. Elixir has a mix task which does something similar. You are creating a release aren’t you ?

The script would take a node name and detects if it is the first node running and creates the dbase if it is. If it is the second node running it modifies the configuration using mnesia:add_table_copy/3.

(2) basically starts your application and does the same as the script.

2 Likes

Thank you for answering.

I have a mix application, no release yet.

Sorry if I don’t get this straight away, I am still new to elixir and erlang. Do you suggest something like this? So the first node creates a schema with just itself and starts mnesia (if Node.list is empty). All subsequent nodes (if Node.list is non-empty) just start mnesia and ask Node 0 to copy over the tables and change the config.
I guess that SyncM library would fall into category (2) while you would do that in some kind of a mix install task?

Hi, there was an article recently on how to set a mnesia up (in Elixir), perhaps it could be of use as a reference. Just scroll down towards the middle for the relevant parts.

5 Likes

I’ve been working on a distributed version of the Mnesia cache for Pow.

In short this is what I’m doing:

Initial node

  1. Start mnesia with :mnesia.start()
  2. Change the copy type with :mnesia.change_table_copy_type(:schema, [node()], copy_type), if you e.g. use disc copies
  3. Create the table :mnesia.create_table(table, table_def)
  4. Wait for the table to be ready :mnesia.wait_for_tables([table], timeout).

Join cluster

  1. Since Pow starts all nodes as disc copies, I’m purging old data and removing the table copy from the cluster
  2. Start mnesia with :mnesia.start()
  3. Join cluster with :mnesia.change_config([:extra_db_nodes, [cluster_node]])
  4. Change table copy type :mnesia.change_table_copy_type(:schema, [node()], copy_type), if you e.g. use disc copies
  5. Sync table :mnesia.add_table_copy([table, node(), copy_type])
  6. Wait for the table to be ready :mnesia.wait_for_tables([table], timeout).

This is done in a GenServer, so happens automatically when my app starts.

5 Likes

Hi @danschultzer, is it possible to please get more information on how you test if a given node is the initial node or not? Thanks.