Mnesia create tables best practices

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Mnesia create tables best practices

Roberto Ostinelli
Dear list,
What best practice do you have when you have a release and want to insure a node has a properly initialised mnesia scheme?

Do you manually bring up all the nodes, then ping them, then go through a standard function which creates schemas and tables, then you shut down your nodes and start your release on the nodes?

Do you instead have a function which check whether mnesia is already initialised every time you start a release? In which case, how do you determine which is the "master" node that will perform the table creation?

Just curious. Until now I have done it with an additional nodetool call that can manually be started with a /myapp/bin/myapp install_db kind of call, but I would like to see if there is a best practice to have it done "automagically".

:)

r.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Jesper Louis Andersen-2

On Sat, Feb 7, 2015 at 7:45 PM, Roberto Ostinelli <[hidden email]> wrote:
Dear list,
What best practice do you have when you have a release and want to insure a node has a properly initialised mnesia scheme?
 
Provide a pre-initialized database with your release. Don't attempt "figuring out" if there is no database and then create it on demand. It just leads to misery.

Your system proper only operates if there is a database. The End. When the release initially boots, there is a complete database, with a complete schema, ready to run, so the nodes can start working immediately. Some times, you will me using a method, where there is a file named FALLBACK.BUP. This is a "fallback" file, which will "restore" the database once the system is booted. This is also how `mnesia:create_schema/2` works, incidentally :P

The beauty of this way is that your system is always in a state where it is "catching up" from a known good state. And you don't have to handle the special case of "initializing", which is completely perpendicular to your normal operation.

Unfortunately, creation of Mnesia databases is not an idempotent operation.

--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Roberto Ostinelli-3

> Some times, you will me using a method, where there is a file named FALLBACK.BUP. This is a "fallback" file, which will "restore" the database once the system is booted. This is also how `mnesia:create_schema/2` works, incidentally :P
>
> The beauty of this way is that your system is always in a state where it is "catching up" from a known good state. And you don't have to handle the special case of "initializing", which is completely perpendicular to your normal operation.

Thank you Jesper. That makes a lot of sense.

Can you please expand on this? Do you mean that when you boot a system you reset the db?

Best,
r.
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Jesper Louis Andersen-2

On Sun, Feb 8, 2015 at 7:25 PM, Roberto Ostinelli <[hidden email]> wrote:
Can you please expand on this? Do you mean that when you boot a system you reset the db?

The DB is never reset. It is just that on the first deploy, there is a valid DB the system can use to start up and get to work. Apart from having the right schema, it can also be pre-populated with important data the systems needs in order to function correctly.




--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Martin Karlsson-2
Hi Jesper,

This is an interesting approach. I've gone the " leads to misery" path :) I.e when a node starts up if it doesn't have a schema it waits for an initialisation command from the use and it can either initialise itself as the first node in the cluster or join another node. I've never been fully happy with this.

How would your approach work with multiple nodes? I can understand starting the first node using a pre-initialised schema but then the other node starts up you want it to be able to join the mnesia cluster in a nice way and not start and initialise its own schema.

An alternative I've also seen is having an mnesia "install" phase and use the erlang boot scripts to kick the install process off.

Cheers,
Martin



On 11 February 2015 at 02:20, Jesper Louis Andersen <[hidden email]> wrote:

On Sun, Feb 8, 2015 at 7:25 PM, Roberto Ostinelli <[hidden email]> wrote:
Can you please expand on this? Do you mean that when you boot a system you reset the db?

The DB is never reset. It is just that on the first deploy, there is a valid DB the system can use to start up and get to work. Apart from having the right schema, it can also be pre-populated with important data the systems needs in order to function correctly.




--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Roberto Ostinelli-3
Adding to this: doesn't it mean that the name and full host of the node need to be known before you can initialize your db, hence a release can only be specific for a specific full node name?



On 10/feb/2015, at 21:57, Martin Karlsson <[hidden email]> wrote:

Hi Jesper,

This is an interesting approach. I've gone the " leads to misery" path :) I.e when a node starts up if it doesn't have a schema it waits for an initialisation command from the use and it can either initialise itself as the first node in the cluster or join another node. I've never been fully happy with this.

How would your approach work with multiple nodes? I can understand starting the first node using a pre-initialised schema but then the other node starts up you want it to be able to join the mnesia cluster in a nice way and not start and initialise its own schema.

An alternative I've also seen is having an mnesia "install" phase and use the erlang boot scripts to kick the install process off.

Cheers,
Martin



On 11 February 2015 at 02:20, Jesper Louis Andersen <[hidden email]> wrote:

On Sun, Feb 8, 2015 at 7:25 PM, Roberto Ostinelli <[hidden email]> wrote:
Can you please expand on this? Do you mean that when you boot a system you reset the db?

The DB is never reset. It is just that on the first deploy, there is a valid DB the system can use to start up and get to work. Apart from having the right schema, it can also be pre-populated with important data the systems needs in order to function correctly.




--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Jesper Louis Andersen-2

On Wed, Feb 11, 2015 at 9:07 AM, Roberto Ostinelli <[hidden email]> wrote:
Adding to this: doesn't it mean that the name and full host of the node need to be known before you can initialize your db, hence a release can only be specific for a specific full node name?

Indeed, distributed mnesia requires a node list when creating the schema. So this makes the database specific to the installation. This is not unique in any way, as RDBMS systems in general has this requirement of "pool initialization", where initial schemas, clustering and replication configuration has to happen. In this case, schema creation needs a separate target, and it is often beneficial to store the mnesia dir outside the release for easier upgrades.

What I'm coming at is that mnesia was not created for idempotent database initialization. Other systems may be far better at this, where one can join new nodes to an existing system dynamically. The task is even automatic in some systems. But for mnesia, you need to write code. Code gives control and flexibility at the expense of simple deployment. On the other hand, you wont be surprised by system behaviour since you wrote the code yourself. Here is one way to go about it.

Initialize a ``root'' which stores the schema and uses a predefined schema upon boot. Every other node now joins the cluster, with an empty schema. You start mnesia on a new node. You call `mnesia:change_config(extra_db_nodes, ['[hidden email]'])` on root followed by `mnesia:change_table_copy(schema, '[hidden email]', disc_copies)` so the schema is on the disc of the newly joined node.

From here, you can run `mnesia:add_table_copy(Table, '[hidden email]', Type)` to copy tables to the newly joined node for the tables which needs to be added.

In turn, you have two release configurations. One in which the node boots with a predefined schema, and one where it boots in a ram_copies schema mode and doesn't start operating before it has been joined to a cluster. Once it has been joined, it has a valid mnesia database and is ready for doing work in the cluster.

If you want the ability to truly elastically add and remove nodes from a cluster, you probably shouldn't use mnesia. The reason has to do with mnesia's inability to automatically work with network splits and split brain. You can add nodes to mnesia ``up to a point'', after which you will have to move to another database system. As I've argued before[0], in the sense of the CAP theorem, mnesia is neither CP, nor AP and ``CA'' doesn't exist as a mode. Remember that mnesia predates the CAP theorem by a couple of years, and partitioning is highly unlikely in a system where communication is on the same cross-backplane as your telephony switching calls. For AP systems, Riak is perhaps the weapon of choice for Erlang programmers. For a CP system, I don't really have a good elastic candidate, but others may.

Where mnesia shines are:

* The cluster is of moderate size, perhaps less than 16 nodes.
* The FULL database can be in memory, or if using fragmented tables, loss of a fragment is not equal to total system catastrophe.
* Interaction between the Erlang processes and the data is tight, so having access to QLC is important.
* You have most queries as K/V lookups requiring microsecond latency with few complicated queries joining many tables. In the latter case, you care about correctness, not latency.
* The most likely failure is loss of a node. It happens rarely and it is possible to solve through manual intervention in a window of a couple of days/weeks.




--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Mnesia create tables best practices

Roberto Ostinelli
Thank you Jesper.

Best,
r.

On Wed, Feb 11, 2015 at 3:01 PM, Jesper Louis Andersen <[hidden email]> wrote:

On Wed, Feb 11, 2015 at 9:07 AM, Roberto Ostinelli <[hidden email]> wrote:
Adding to this: doesn't it mean that the name and full host of the node need to be known before you can initialize your db, hence a release can only be specific for a specific full node name?

Indeed, distributed mnesia requires a node list when creating the schema. So this makes the database specific to the installation. This is not unique in any way, as RDBMS systems in general has this requirement of "pool initialization", where initial schemas, clustering and replication configuration has to happen. In this case, schema creation needs a separate target, and it is often beneficial to store the mnesia dir outside the release for easier upgrades.

What I'm coming at is that mnesia was not created for idempotent database initialization. Other systems may be far better at this, where one can join new nodes to an existing system dynamically. The task is even automatic in some systems. But for mnesia, you need to write code. Code gives control and flexibility at the expense of simple deployment. On the other hand, you wont be surprised by system behaviour since you wrote the code yourself. Here is one way to go about it.

Initialize a ``root'' which stores the schema and uses a predefined schema upon boot. Every other node now joins the cluster, with an empty schema. You start mnesia on a new node. You call `mnesia:change_config(extra_db_nodes, ['[hidden email]'])` on root followed by `mnesia:change_table_copy(schema, '[hidden email]', disc_copies)` so the schema is on the disc of the newly joined node.

From here, you can run `mnesia:add_table_copy(Table, '[hidden email]', Type)` to copy tables to the newly joined node for the tables which needs to be added.

In turn, you have two release configurations. One in which the node boots with a predefined schema, and one where it boots in a ram_copies schema mode and doesn't start operating before it has been joined to a cluster. Once it has been joined, it has a valid mnesia database and is ready for doing work in the cluster.

If you want the ability to truly elastically add and remove nodes from a cluster, you probably shouldn't use mnesia. The reason has to do with mnesia's inability to automatically work with network splits and split brain. You can add nodes to mnesia ``up to a point'', after which you will have to move to another database system. As I've argued before[0], in the sense of the CAP theorem, mnesia is neither CP, nor AP and ``CA'' doesn't exist as a mode. Remember that mnesia predates the CAP theorem by a couple of years, and partitioning is highly unlikely in a system where communication is on the same cross-backplane as your telephony switching calls. For AP systems, Riak is perhaps the weapon of choice for Erlang programmers. For a CP system, I don't really have a good elastic candidate, but others may.

Where mnesia shines are:

* The cluster is of moderate size, perhaps less than 16 nodes.
* The FULL database can be in memory, or if using fragmented tables, loss of a fragment is not equal to total system catastrophe.
* Interaction between the Erlang processes and the data is tight, so having access to QLC is important.
* You have most queries as K/V lookups requiring microsecond latency with few complicated queries joining many tables. In the latter case, you care about correctness, not latency.
* The most likely failure is loss of a node. It happens rarely and it is possible to solve through manual intervention in a window of a couple of days/weeks.




--
J.


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions