2012-04-14 22 views
11

OSTRZEŻENIE: Informacje podstawowe są dość długie. Przejdź na sam dół, jeśli uważasz, że potrzebujesz pytania przed informacją w tle. Doceń czas, jaki to zajmie!jaki jest właściwy sposób tworzenia kopii zapasowych/przywracania bazy danych mnesii?

Byłem w Internecie (czytaj google) i nie znalazłem dobrej odpowiedzi. TAK, istnieje wiele linków i odnośników do dokumentacji Mnesii na stronie erlang.org, ale nawet te linki cierpią na wersję-itis.

Tak więc w najprostszym przypadku, gdy węzeł(), z którym obecnie się łączysz jest taki sam, jak właściciel zestawu tabel, będzie działał backup/przywracanie. Na przykład:

$ erl -sname mydatabase 

> mnesia:start(). 
> mnesia:create_schema(...). 
> mnesia:create_table(...). 
> mnesia:backup("/tmp/backup.bup"). 
> mnesia:restore("/tmp/backup.bup", [{default_op, recreate_tables}]). 

Hej, działa to świetnie!

Jednakże, jeśli baza danych jest uruchomiony na zdalnym węźle() lub zdalnego węzła() na zdalnym kryciem potem trzeba inicjować tworzenie kopii zapasowej w ten sposób:

$ erl -sname mydbadmin 

> rpc:call([email protected], mnesia, backup, ["/tmp/backup.bup"]). 
> rpc:call([email protected], mnesia, restore, ["/tmp/backup.bup", [{default_op, recreate_tables}]]). 

Oczywiście to proste także. Teraz są trudne rzeczy ...

  • Załóżmy, że codziennie robisz kopie zapasowe. A ty serwer bazy danych mnesii umiera i musisz wymusić wymianę sprzętu. Jeśli chcesz przywrócić DB jako taki, musisz nazwać NOWY sprzęt o tej samej nazwie, co poprzednio, a także musisz nazwać węzły tym samym.
  • Jeśli chcesz zmienić nazwę sprzętu i/lub węzła() ... lub chcesz przywrócić na innym komputerze, musisz przejść przez proces node_change. (opisane here i w dokumentach mnesia)

Ale tutaj sprawy się komplikują. Podczas gdy moi znajomi, którzy są ekspertami od erlang i mnesii, sugerują, że replikacja mnesii jest poważnie wadliwa i że nie powinieneś jej używać (obecnie nie ma alternatyw, które znam i jakie są szanse, że zamierzasz wprowadzić lepszą wersję, a nie prawdopodobnie)

Masz zatem dwa węzły(), które replikują tabele ram i dyskowe. Prowadzisz politykę regularnego tworzenia kopii zapasowej bazy danych za pomocą standardowej kopii zapasowej przy użyciu domyślnego BackupMod. Pewnego dnia menedżer prosi o zweryfikowanie kopii zapasowych. Tylko wtedy, gdy próbują przywrócić bazę danych można uzyskać:

{atomic,[]} 

I według dokumentacji oznacza to, że nie było żadnych błędów ... i jeszcze zostały przywrócone żadne tabele.

Nie chcąc uruchomić procedury change_node, pamiętaj, że węzeł() i nazwa hosta muszą się zgadzać, aby zmienić nazwę hosta i parametr -sname na zgodny z maszyną, na której dane zostały zarchiwizowane. Tym razem jednak pojawi się dziwny błąd:

{aborted,{'EXIT',{aborted,{bad_commit,{missing_lock,[email protected]}}}}} 

Nadal nie chcąc uruchomić procedurę change_node szybko sklonować przywrócić mój serwer tak, że mam dwóch podobnych maszyn. W takim razie nazwę odpowiednio do serwerów produkcyjnych. I rozpoczynam proces przywracania. Eureka! Mam teraz prawdziwe dane robocze na serwerach przywracania.

Chciałbym powiedzieć, że to był koniec drogi ... ale nie zadałem jeszcze pytania i że chodzi o SO .... więc oto jest?

PYTANIE: jeśli chcę przywrócić kopię zapasową, która została podjęta z klastra replikowane węzłów mnesia, w jaki sposób zmodyfikować plik (podobna do procedury change_node) tak, że inne węzły są albo ignorowane lub usuwane z kopia zapasowa?

Zapytany nieco inaczej: Jak przywrócić wielopunktową (mnesia) replikowaną bazę danych w jednym węźle()?

+0

Powinien również zobaczyć http://stackoverflow.com/questions/463400/how-to-rename-node-running-a-mnesia-database. –

Odpowiedz

7

myślę, że problem ten mieści się w szerszej kategorii pytań Mnesia, które są związane z proste:

How do I rename a Mnesia node?

Pierwszym i najprostszym rozwiązaniem, jeśli db nie jest ogromny, jest użycie mnesia : funkcja traverse_backup (patrz Mnesia User guide). Poniżej przykład z podręcznika użytkownika Mnesia:

change_node_name(Mod, From, To, Source, Target) -> 
    Switch = 
     fun(Node) when Node == From -> To; 
      (Node) when Node == To -> throw({error, already_exists}); 
      (Node) -> Node 
     end, 
    Convert = 
     fun({schema, db_nodes, Nodes}, Acc) -> 
       {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc}; 
      ({schema, version, Version}, Acc) -> 
       {[{schema, version, Version}], Acc}; 
      ({schema, cookie, Cookie}, Acc) -> 
       {[{schema, cookie, Cookie}], Acc}; 
      ({schema, Tab, CreateList}, Acc) -> 
       Keys = [ram_copies, disc_copies, disc_only_copies], 
       OptSwitch = 
        fun({Key, Val}) -> 
          case lists:member(Key, Keys) of 
           true -> {Key, lists:map(Switch, Val)}; 
           false-> {Key, Val} 
          end 
        end, 
       {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc}; 
      (Other, Acc) -> 
       {[Other], Acc} 
     end, 
    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched). 

view(Source, Mod) -> 
    View = fun(Item, Acc) -> 
        io:format("~p.~n",[Item]), 
        {[Item], Acc + 1} 
      end, 
    mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0). 

Najważniejszym elementem jest tu manipulacja {schema, db_nodes, Nodes} krotki które pozwalają zmienić nazwę lub zastąpić węzły dB.

BTW, użyłem tej funkcji w przeszłości i zauważyłem, że format warunków tworzenia kopii zapasowych zmienia się między wersjami mnesia, ale może to po prostu pisanie złego kodu. Wystarczy wydrukować dziennik kopii zapasowej małej bazy danych mnesii, aby sprawdzić format daty kopii zapasowej, jeśli chcesz mieć pewność.

Mam nadzieję, że to pomoże!

+0

Mam tekst i nie mówi nic o kopiowaniu lub przywracaniu klastra serwerów mnesii. – Richard

+0

W swoim pytaniu napisałeś, że wiesz o przykładowym węźle zmiany, który jest również zawarty w dokumencie, który wskazałem. Jeśli dobrze rozumiem twoje pytanie, w tym samym przykładzie widać, że sprawdzana jest krotka {schemat, węzły_db, węzły}: ta krotka zawiera węzły zarejestrowane dla bazy danych Mnesii. –

+0

Ah! Brakowało mi tego w kodzie change_node. (twoja odpowiedź nic o tym nie mówi, jednak poprawna odpowiedź byłaby poprawna.) Dziękuję. – Richard