суббота, 5 ноября 2011 г.

Mnesia - изменение таблицы

Erlang - интересная вещь. Обещает много полезного и быстрого. Например,  база данных Mnesia. В Mnesia много всего полезного: хранит данные в формате Erlang, репликация, транзакции, скорость и т.д. и т.п. Но есть одна проблемка - как изменить структур таблицы?

При создании таблицы необходимо указать список полей. Не будем сейчас углубляться в  рекомендации использовать  запись (record) одноименную с таблицей. Важно, что при изменении списка полей по предлагаемому варианту с простым  использованием  mnesia:transform_table (конвертирование полей и замена определения таблицы), похоже, придется останавливать работу системы, конвертировать, менять код приложения для работы с новым типом и запуск (тестирование).
Если посмотреть на тоже MS SQL то добавление поля - элементарная операция.
Для меня важно провести переход на новый тип без остановки всей системы. По крайнеё мере БД должна функционировать непрерывно.

Я исследовал чтение и запись в Mnesia. И вывод таков:
Mnesia жестко контролирует данные при записи. Записать можно только то что обявлено в структуре таблицы, иначе ошибка. Контролируется имя записи и количеств элементов -  т.е. ВСЕ.
Однако, при чтении  Mnesia отдает то, что было записано, не сверься с текущим сконфигурированным списком полей и названием записи. И список полей можно изменить и без фактической трансформации (mnesia:transform_table(Tab,ignore, Fildlist ).
Для примера создадим таблицу, запишем данные , а потом добавим новые поля:

-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).


Испытаем:



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}]

Теперь у нас в таблице записи обоих типов и мы их можем прочитать. Но если мы теперь попытаемся создать индекс на четвертом поле записи mnesia:add_table_index(r1,[l4]).
- мы получим фатальную ошибку, остановку mnesia и при следующем запуске этой базы снова произойдет ошибка. Поможет только удаление файла r1.dcm -  только после этого mnesia запустится. Необходимо будет еще удлаить определение таблицы из схемы.
Следовательно, пока все записи в таблицы не будут соответствовать спецификации индекса - ни в коем случае не индексировать.





Комментариев нет: