W poprzednich postach pisałem o tym, jak wygląda sytuacja, gdy wypinamy wtyczkę z kontaktu – jak wygląda wymuszony restart serwera MySQL, jak wygląda odtwarzanie danych z kopii zapasowej? Niektórzy administratorzy MySQL, na wypadek zajścia takiej sytuacji, stosują różnorakie mechanizmy gwarantujące pewien poziom dostępności usług. W tym poście opiszę pokrótce dwa takie rozwiązania, omówimy także jak to się ma do wyboru silnika bazodanowego.

Jednym z mechanizmów zapewnienia dostępności danych, który jest powszechnie stosowany, to replikacja. To, czy replikacja jest rozwiązaniem, które można traktować jako tzw. „high availability”, to kwestia dyskusyjna. Podstawowym problemem jest to, że nie daje ona gwarancji, że wszystkie zmiany zdążą się rozpropagować. Może się okazać, że w danej, krytycznej chwili, slave nie nadążał za masterem i w efekcie nie wszystkie zmiany się zreplikowały. Nie mniej jednak, replikacja to najprostszy sposób, aby utrzymać dostępność usługi. Brakujące dane zazwyczaj można odzyskać, jak już administrator upora się z awarią serwera, natomiast często jest tak, że w danym, konkretnym momencie ważniejsze jest, aby jakiekolwiek dane były serwowane, nawet jeśli nie są to dane idealnie kompletne. Tak na marginesie, kwestia replikacji na pewno będzie poruszana na tym blogu, ale na razie, jeśli ktoś chciałby się dowiedzieć więcej, z czym się to je, proponuję zapoznać się z dokumentacją MySQL.

Jak to wygląda jeśli chodzi o silniki bazodanowe? Replikacja zasadniczo jest od nich niezależna. Zmiany są replikowane z mastera na slave jako informacje o wykonywanych zapytaniach (czyli po prostu, jaki INSERT/UPDATE/DELETE/cokolwiek innego był uruchamiany na masterze), bądź też jako informacje o tym, które rekordy i w jaki sposób zostały zmodyfikowane. Są jednak pewne sytuacje, gdzie silnik bazy danych ma znaczenie. Jedną z takich sytuacji jest to, gdy administrator pracuje na masterze w trybie interaktywnym. Załóżmy, że chcemy wykonać jakieś nietypowe zapytanie – wyciągamy dużą ilość danych, na ich podstawie modyfikujemy inne dane. Zapytanie trwa długo, w tym czasie administrator traci połączenie z serwerem, albo po prostu rozmyśla się i przerywa działanie zapytania. W przypadku, gdy modyfikowane były dane w tabeli InnoDB, nie dzieje się nic. Transakcja nie została zakończona, zmiany zostają cofnięte. W przypadku MyISAM jest już gorzej – zapytanie jest przerwane, do binlogów nie trafi, ale te rekordy, które zmodyfikowało, zmodyfikowane pozostaną. Zmiany te nie zreplikują się na slave, powstaje różnica w zawartości obu serwerów.

Drugim mechanizmem, o którym chcę wspomnieć, to klaster active – passive działający na jednym zestawie danych. Klaster ten funkcjonuje na takiej zasadzie, że jednorazowo działa tylko jeden serwer, a drugi pozostaje nieaktywny. Jeśli aktywny serwer z jakiegoś względu przestanie odpowiadać, uruchamiany jest drugi serwer, który przejmuje rolę serwera aktywnego. Tego typu operacje można bardzo przyjemnie zautomatyzować przy pomocy skryptów czy dostępnych w Internecie aplikacji do zarządzania klastrem (jak np. Pacemaker). Kluczową sprawą jest tu współdzielenie zestawu danych – czy będzie się to odbywało przez jakiegoś rodzaju macierz, czy też zastosowane zostanie drbd. Dzięki temu jest prawie 100% pewności (niestety, drbd potencjalnie może zawieść), że po wyłączeniu głównego serwera i przepięciu ruchu na zapasowy, dane na serwerze zapasowym będą identyczne z tymi na głównym. Ta zaleta staje się także główną wadą. Opisywałem jak wygląda proces uruchamiania się serwera po awarii. Dokładnie tak samo wygląda uruchamianie się serwera zapasowego w przypadku klastra active – passive. Nic w tym dziwnego, w końcu działa on na tych samych danych, na których działał uszkodzony serwer główny. MySQL nie zamknął się poprawnie, transakcje w logu InnoDB nie zostały zapisane do tablespace, tabele MyISAM, które były otwarte w czasie awarii mogły zostać uszkodzone. Długotrwały proces naprawy tabel MyISAM jest przyczyną tego, że w klastrze active – passive jedynym sensownym rozwiązaniem jest stosowanie InnoDB. Proces uruchamiania się InnoDB po awarii jest znacznie krótszy od czasu potrzebnego do naprawy kilkuset mega tabeli MyISAM. Dodatkowo, długość tego procesu można zmniejszyć zmniejszając wielkość pliku logu transakcji. Ma to też oczywiście inne, negatywne skutki (jak choćby zwiększony ruch na dysku związany z koniecznością częstszego aplikowania zawartości logu do danych na dysku), ale przynajmniej można o nich samemu decydować.