⬆️ ⬇️

Mnesia - change table

Mnesia has a lot of useful things: it stores data in Erlang format, replication, transactions, etc. etc. But there is one problem - how to change table structures?



When creating a table, you must specify a list of fields. We will not go deep into recommendations to use record (record) with the same name with the table. It is important that when changing the list of fields for the proposed documentation using mnesia: transform_table (converting fields and replacing the table definition), it seems you will have to stop the system, convert the table, change the application code to work with the new type and start (test).

If you look at any SQL database, then adding a field is an elementary operation.

For me it is important to make the transition to a new type without stopping the entire system. At least, the database should function continuously.



I researched reading and writing in Mnesia. And the conclusion is:

Mnesia tightly controls the data while recording. You can only record what is declared in the table structure, otherwise it is an error. The name of the record and the number of elements is controlled - i.e. EVERYTHING.

However, when reading, Mnesia gives away what was written, not referring to the currently configured list of fields and the title of the record. And the list of fields can be changed without actually transforming the records using the non-recommended mnesia form: transform_table (Tab, ignore , Fildlist).

This form is intended, according to the documentation, for custom transformation of table entries.

Let's see how it all works. For example, create a table, write the data, and then add new fields and transform with ignore:

-module(recordtest).

-compile(export_all).

-record(r1 ,{f1,f2}).

-record(r2 ,{f1,f2,f3,f4}).

dbtest()->

mnesia:create_table(r1,[{attributes, record_info(fields, r1)}]).

transform()->

mnesia:transform_table(r1,ignore,record_info(fields, r2), r2).





Test:



14> mnesia:create_schema([node()]).

18> mnesia:start().

ok

19> recordtest:dbtest().

{atomic,ok}

20> mnesia:dirty_write(r1, {r1,l1,l2}).

ok

21> mnesia:dirty_write(r1, {r1,t1,t2,t3}).

** exception exit: {aborted,{bad_type,{r1,t1,t2,t3}}}

in function mnesia:abort/1

22> mnesia:dirty_write(r1, {r2,l1,l2}).

** exception exit: {aborted,{bad_type,{r2,l1,l2}}}

in function mnesia:abort/1

23> mnesia:dirty_read(r1, l1).

[{r1,l1,l2}]

24> mnesia:dirty_read(r1, l1).

[{r1,l1,l2}]



38> recordtest:transform().

{atomic,ok}

39> mnesia:dirty_read(r1, l1).

[{r1,l1,l2}]

40> mnesia:dirty_write(r1, {r2,l1,l2}).

** exception exit: {aborted,{bad_type,{r2,l1,l2}}}

in function mnesia:abort/1

41> mnesia:dirty_write(r1, {r2,a1,a2,a3,a4}).

ok

49> mnesia:dirty_read(r1, l1).

[{r1,l1,l2}]

50> mnesia:dirty_read(r1, a1).

[{r2,a1,a2,a3,a4}]




Now we have records of both types in the table and we can read them. But if we now try to create an index on the fourth field of the mnesia:add_table_index(r1,[l4]).

- get a fatal error, stop mnesia. The next time you run this database, an error will occur again. Removal of the file r1.dcm will help - after that mnesia will start. You will still need to remove the table definition from the schema.

Consequently, as long as all the records in the tables do not meet the index specification, in no case can you index them.

')

Based on the above, it can be argued that the transformation of the mnesia tables is quite a serious problem. Apparently, it is necessary in advance, at the design stage, to provide for the modes of operation of the system for the transformation of tables.

The possibility of functioning in a transient mode is also demonstrated, when both new type and old type records are placed in the table. How exactly to complete the transition to a new record type (get rid of the old type of records) depends on the specific system.



If anyone is familiar with the problem of changing tables in Mnesia - share. There is very little information about Mnesia.

Source: https://habr.com/ru/post/140811/



All Articles