Czasami zdarza się sytuacja, w której trzeba szybko przenieść dane z serwera na serwer. Wykonanie zrzutu i wgranie go niestety trwa. Co można zrobić aby przyspieszyć ten proces? Rozwiązaniem jest po prostu przegranie plików z serwera na serwer. Zazwyczaj rsync plików z danymi pomiędzy serwerami będzie znacznie szybszy niż dump/reload. Jak to wygląda w praktyce i na co trzeba uważać?
W poście dotyczącym backupu, przy okazji opisywania różnic pomiędzy MyISAM a InnoDB, wspominałem o niektórych elementach. W końcu backup binarny to też przeniesienie danych z serwera na serwer. Tym razem jednak postaram się opisać całość dokładniej.
W przypadku tabel działających na silniku MyISAM sprawa jest prosta. Wystarczy zablokować tabelę do zapisu, a następnie można skopiować na bok odpowiednie pliki *.frm, *.MYI i *.MYD. Czy założymy read lock na tabelę, czy uruchomimy FLUSH TABLES WITH READ LOCK;, czy też po prostu wyłączymy serwer – jeśli tabela nie może być zapisana, nie ma problemu aby ją przegrać gdziekolwiek na inny serwer.
InnoDB trochę komplikuje tą sprawę. Tak jak pisałem we wspominanym poście, jedyny sposób aby być pewnym, że po przegraniu wszystkich plików na nowy serwer dane będą na miejscu, jest wyłączenie serwera źródłowego przed wykonaniem kopii jego zawartości. Dopiero wtedy wszystkie informacje o modyfikacjach, które siedziały w buforze logu InnoDB w pamięci, trafią do plików logów na dysku.
Ok. Co trzeba przegrać aby wszystkie dane były na miejscu? Zawartość trzech katalogów, na które wskazują następujące zmienne:
SHOW VARIABLES LIKE 'innodb_data_home_dir';
SHOW VARIABLES LIKE 'innodb_log_group_home_dir';
Pierwszy to katalog z wszystkimi bazami danych – w przypadku MyISAM znajdują się tam wszystkie dane, w przypadku InnoDB może być różnie. Na pewno są tam definicje tabel w postaci plików *.frm. Jeśli mamy ustawione:
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.00 sec)
to prawdopodobnie znajdują się tam także pliki *.ibd – tablespace dla danej, konkretnej tabeli.
Drugi katalog, ‚innodb_data_home_dir’, to miejsce, gdzie znajduje się współdzielony tablespace. W domyślnej konfiguracji InnoDB przechowywane są tam wszystkie dane. Jeśli włączyliśmy ‚innodb_file_per_table’, to we współdzielonym tablespace znajdują się dane dotyczące tabel, które powstały przed zmianą tego ustawienia. Nawet jeżeli taką konfigurację mamy od początku działania serwera, to współdzielony tablespace jest potrzebny – przechowywane są w nim informacje o tym, jakie tabele istnieją. Dla InnoDB pliki *.frm nie wystarczą. Sama informacja w tablespace także nie. Aby tabela była poprawnie dostępna, muszą być zachowane obie te informacje.
Trzeci katalog to katalog z logami transakcji InnoDB – są one potrzebne do tego, aby InnoDB na nowym serwerze mogło poprawnie się uruchomić i aby zachowana była spójność danych. Więcej na temat procesu startu InnoDB można przeczytać w tym poście.
Wiemy już co trzeba przegrać aby zachować wszystkie dane. Na co trzeba uważać podczas tego typu operacji?
Po pierwsze, jako że musimy przegrać współdzielony tablespace, jedyną możliwością jest przegrywanie danych na pusty serwer. Współdzielone tablespace przechowuje dane o istniejących tabelach. Współdzielone tablespace na serwerze docelowym musi zostać nadpisane. Jeśli na tym serwerze były jakiekolwiek tabele InnoDB, informacje o nich są tracone – pozostają osierocone pliki *.frm i InnoDB będzie krzyczeć w logach, że coś mocno nie gra.
Po drugie, muszą zostać zachowane pewne warunki – ogólnie, chodzi o kompatybilność binarną obu serwerów. Konkretnie wygląda to tak:
– obie maszyny muszą używać kompatybilnej arytmetyki stałoprzecinkowej
– obie maszyny muszą używać formatu zmiennoprzecinkowego definiowanego przez IEEE, ewentualnie tabele nie mogą posiadać kolumn o typach zmiennoprzecinkowych
Te dwa warunki nie stanowią problemu, o ile nie przenosimy danych między dziwnymi architekturami procesorów. Większym problemem może być trzeci:
– nazwy tabel i baz danych nie mogą używać wielkich liter
Chodzi tu o fakt, że w przypadku systemów Windows InnoDB przechowuje dane o bazach i tabelach we współdzielonym tablespace tylko przy użyciu małych liter. W przypadku systemów Unix-pochodnych (jak Linux czy BSD) InnoDB stosuje małe i wielkie litery. Jeśli więc tabelę nazwiemy np. ‚Tabela’, to z Linuksa na Linux dane przeniesiemy bez problemu. W przypadku przenosin z Linuksa na Windows pojawi się problem.
Jak widać, jeśli będziemy uważać, przenoszenie danych z serwera na serwer w postaci binarnej jest możliwe do wykonania także w przypadku InnoDB. Nie da się jednak ukryć, że nie jest to tak wygodne jak dump i reload. Szybsze tak, wygodniejsze, nie. Co więcej, decydując się na sposób przenoszenia danych trzeba wziąć pod uwagę, że mysqldump ma dodatkową zaletę. Tablespace InnoDB mogą tylko rosnąć. Jeśli tabela rozrośnie się do kilku gigabajtów, to wykonanie TRUNCATE TABLE; nie odzyska miejsca na dysku. W przypadku włączonego innodb_file_per_table, odzyskać dane można tylko przez usunięcie tabeli, w przypadku współdzielonego tablespace nawet to nie pomoże. Wgranie danych na nowy serwer ze zrzutu zoptymalizuje ilość miejsca na dysku potrzebne dla InnoDB – po wgraniu dumpa zajętego dysku będzie tylko tyle, ile faktycznie jest na ten moment potrzebne.
Komentarze