Tak jak pisałem w poprzednim poście do przenoszenia informacji o modyfikacjach MySQL stosuje binlogi. Replikacja MySQL może działać w trzech trybach, które przekładają się na to, co do binlogów jest zapisywane – row-based replication (RBR), statement-based replication (SBR) i mieszanka obu trybów. Ustawia się to przy pomocy zmiennej binlog_format, która może przyjąć wartość ROW, STATEMENT i MIXED.

SBR to tryb, który przed MySQL 5.1.4 był jedynym dostępnym. W tym trybie przesyłane są informacje o tym, jakie zapytania były wykonane. Slave dostaje informację, że wykonany został:

UPDATE tabela SET kolumna='1' WHERE id=10;

i wykonuje dokładnie takie samo zapytanie u siebie. Tryb ten powodował pewne problemy z replikowaniem działania procedur składowanych. Załóżmy, że procedura modyfikuje dane w sposób nieprzewidywalny – np. losuje sobie coś i na tej podstawie wykonuje jakieś zapytania. Zreplikowanie wywołania takiej procedury skutkować będzie zupełnie innymi modyfikacjami na slave – po prostu wylosuje się coś innego. Z tego powodu wprowadzono drugi tryb replikacji – row-based replication. W trybie tym do binlogów zapisywane są nie tyle zapytania, które były wykonywane, co skutek ich działania – jakie rekordy w jaki sposób zostały zmienione. Dzięki temu nie ma problemu z działaniem procedur, który opisywałem powyżej. Jako, że replikacja zapytań zazwyczaj bywa bardziej wydajna niż replikacja zmian, powstał tryb łączący oba wcześniejsze. W trybie MIXED domyślnie wykorzystywany jest tryb statement-based replication, natomiast w ściśle określonych sytuacjach, gdy efekt działania danego zapytania nie jest przewidywalny, włączany jest tryb zapisywania modyfikacji rekordów.

Kolejną cechą charakterystyczną dla replikacji MySQL jest to, że jest ona asynchroniczna – nie mamy żadnej pewności, że po zakończeniu transakcji na masterze dane się gdziekolwiek zreplikowały. Jeśli wykonujemy COMMIT kończący transakcję, zakładając, że MySQL skonfigurowany jest tak, że wspiera ACID, chcemy być pewni, że zmiany w danych zostały zapisane. Oczywiście, do tego musimy korzystać z silnika transakcyjnego, czyli np. InnoDB, bo w przypadku MyISAM nie możemy być pewni niczego. Problem w tym, że pewność ta dotyczy tylko i wyłącznie serwera, na którym wykonywaliśmy transakcję. Załóżmy, że sekundę później master się wyłącza. Aplikacja jest oskryptowana, cały ruch pięknie przełącza się na serwer slave. Okazuje się jednak, że nie ma śladu po wykonanej przez nas modyfikacji danych. Cóż, pech. Akurat slave chwilowo nie nadążał za masterem i zmiany nie zdążyły się zreplikować przed padem.

Rozwiązaniem, które wprowadzone zostało w MySQL 5.5, a także istnieje w postaci patchy do starszych wersji MySQL, jest replikacja półsynchroniczna (semisynchronous replication). W tym przypadku sprawa wygląda następująco. Użytkownik zamyka transakcję, wykonuje COMMIT. Czeka. W tym czasie master wysyła dane do slave, który zapisuje sobie otrzymane logi w postaci relay-logów. W momencie gdy logi zostały zapisane bezpiecznie na dysku, przesyłana jest informacja do mastera. W momencie gdy master otrzymał potwierdzenie przynajmniej od jednego ze slave, transakcja traktowana jest jako zakończona i COMMIT jest zakończony.

Kolejną ważną kwestią do poruszenia jest to, czym replikacja nie jest. Replikacja nie jest sposobem na realizowanie backupu. Można co prawda wykorzystać ją aby odciążyć mastera z procesu wykonywania kopii zapasowej, bo skoro slave jest jego kopią, to wystarczy wykonać backup na mniej obciążonym serwerze slave. Można go też na chwilę wyłączyć i wykonać kopię plików na dysku. Ważnym jest jednak aby każdy administrator MySQL pamiętał, że sama replikacja nie jest i nigdy nie będzie sposobem na wykonanie backupu. W jaki niby sposób taki backup miałby zabezpieczyć nas przed przypadkowym usunięciem tabeli? Przecież DROP TABLE tabela; szybko się zreplikuje i tabela zostanie usunięta także na naszym „backupie”. Są różne sposoby, aby przesunąć w czasie replikację na slave. Przykładowo można do tego wykorzystać program mk-slave-delay. Nowo wydany MySQL 5.6 także udostępnia taką opcję. Problem tylko w tym, że nadal jest to przesunięcie tylko o jakiś czas. Pomoże jeśli od razu zorientujemy się, że coś jest nie tak, ale już nie pomoże, jeśli zorientujemy się po dwóch dniach. Replikacja może służyć tylko i wyłącznie jako źródło danych na wypadek awarii serwera głównego – nie zabezpieczy przed błędami w zapytaniach modyfikujących dane. Niby jest to oczywiste, ale niektórym administratorom zdarza się o tym zapomnieć.