W tym poście na blogu przyjrzymy się, jak przeprowadzić migrację online z samodzielnej konfiguracji MySQL 5.6 do nowego zestawu replikacji działającego na MySQL 5.7, wdrożonego i zarządzanego przez ClusterControl.
Plan polega na skonfigurowaniu łącza replikacji z nowego klastra działającego na MySQL 5.7 do głównego działającego na MySQL 5.6 (poza przepisem ClusterControl), który nie używa identyfikatora GTID. MySQL nie obsługuje mieszania GTID i innych niż GTID w jednym łańcuchu replikacji. Dlatego musimy wykonać kilka sztuczek, aby przełączać się między trybami bez GTID i GTID podczas migracji.
Naszą architekturę i plan migracji można zilustrować poniżej:
Konfiguracja składa się z 4 serwerów o następującej reprezentacji:
- mysql56a - Stary mistrz - Oracle MySQL 5.6 bez GTID
- Klaster podrzędny:
- mysql57a - Nowy master - Oracle MySQL 5.7 z GTID
- mysql57b - Nowy slave - Oracle MySQL 5.7 z GTID
- cc — ClusterControl Server — Serwer wdrażania/zarządzania/monitorowania dla węzłów bazy danych.
Wszystkie hosty MySQL 5.7 działają na Debianie 10 (Buster), podczas gdy MySQL 5.6 działa na Debianie 9 (Stretch).
Wdrażanie klastra niewolników
Najpierw przygotujmy klaster slave, zanim skonfigurujemy łącze replikacji ze starego mastera. Ostateczna konfiguracja klastra podrzędnego będzie działać na MySQL 5.7 z włączonym GTID. Zainstaluj ClusterControl na serwerze ClusterControl (cc):
$ wget https://severalnines.com/downloads/install-cc
$ chmod 755 install-cc
$ ./install-cc
Postępuj zgodnie z instrukcjami aż do zakończenia instalacji. Następnie skonfiguruj bezhasłowe SSH z ClusterControl do mysql57a i mysql57b:
$ whoami
root
$ ssh-keygen -t rsa # press Enter on all prompts
$ ssh-copy-id [email protected] # enter the target host root password
$ ssh-copy-id [email protected] # enter the target host root password
Następnie zaloguj się do interfejsu użytkownika ClusterControl, wypełnij formularz początkowy i przejdź do sekcji ClusterControl -> Wdrażanie -> Replikacja MySQL i wypełnij następujące dane:
Następnie kliknij Kontynuuj i wybierz Oracle jako dostawcę oraz 5.7 jako dostawcę wersja. Następnie przejdź do sekcji topologii i skonfiguruj ją jak poniżej:
Poczekaj na zakończenie wdrażania i powinieneś zobaczyć nowy klaster, jak poniżej:
Nasz klaster podrzędny działający na MySQL 5.7 z GTID jest już gotowy.
Przygotowywanie starego mistrza
Obecny master, który chcemy zreplikować, to samodzielny MySQL 5.6 (włączony log binarny, skonfigurowany identyfikator serwera, bez GTID) i obsługuje produkcyjne bazy danych. Tak więc przestój nie jest opcją dla tej migracji. Z drugiej strony, ClusterControl konfiguruje nowy MySQL 5.7 z włączoną obsługą GTID, co oznacza, że musimy wyłączyć funkcjonalność GTID wewnątrz klastra slave, aby móc poprawnie replikować z tego samodzielnego mastera.
Poniższe wiersze pokazują naszą aktualną konfigurację związaną z replikacją dla głównego /etc/mysql/mysql.conf.d/mysqld.cnf zgodnie z dyrektywą [mysqld]:
server_id=1
binlog_format=ROW
log_bin=binlog
log_slave_updates=1
relay_log=relay-bin
expire_logs_days=7
sync_binlog=1
Sprawdź, czy serwer MySQL generuje dziennik binarny bez GTID:
mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000007 | 734310 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
W przypadku numeru innego niż GTID, Executed_Gtid_Set powinien być pusty. Zwróć uwagę, że nasz nowy klaster replikacji MySQL 5.7 wdrożony przez ClusterControl jest skonfigurowany z włączonym GTID.
1) Utwórz użytkownika replikacji, który będzie używany przez mysql57a:
mysql> CREATE USER 'slave'@'192.168.10.31' IDENTIFIED BY 'slavepassword';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave'@192.168.10.31';
2) Wyłącz automatyczne odzyskiwanie ClusterControl. W interfejsie ClusterControl -> wybierz klaster -> upewnij się, że klaster i węzeł automatycznego odzyskiwania są WYŁĄCZONE (czerwone ikony zasilania), jak pokazano na poniższym zrzucie ekranu:
Nie chcemy, aby ClusterControl odzyskiwał węzeł podczas tej konfiguracji replikacji.
3) Teraz musimy utworzyć pełną kopię zapasową mysqldump, ponieważ będzie to aktualizacja głównej wersji. Inne nieblokujące narzędzia do tworzenia kopii zapasowych, takie jak Percona Xtrabackup lub MySQL Enterprise Backup, nie obsługują przywracania do innej wersji głównej. Musimy również zachować bieżący plik dziennika binarnego i pozycję za pomocą flagi --master-data:
$ mysqldump -u root -p --single-transaction --master-data=2 --all-databases > mysql56a-fullbackup.sql
Zauważ, że powyższe polecenie nie zablokuje żadnych tabel InnoDB z powodu --single-transaction. Więc jeśli masz tabele MyISAM, będą one blokowane w okresie tworzenia kopii zapasowych, aby zachować spójność.
4) Skopiuj kopię zapasową z mysql56a do mysql57a i mysql57b:
$ scp mysql56a-fullbackup.sql [email protected]:~
$ scp mysql56a-fullbackup.sql [email protected]:~
Przygotowywanie klastra Slave
W tej fazie skonfigurujemy klaster podrzędny tak, aby rozpoczął replikację ze starego mastera, mysql56a bez GTID.
1) Zatrzymaj replikację między mysql57a i mysql57b, usuń wszystkie poświadczenia związane z urządzeniami podrzędnymi skonfigurowane przez ClusterControl i wyłącz tylko do odczytu na mysql57b:
mysql> STOP SLAVE;
mysql> RESET SLAVE ALL;
mysql> SET GLOBAL super_read_only = 0;
mysql> SET GLOBAL read_only = 0;
2) Wyłącz GTID w mysql57a:
mysql> SET GLOBAL gtid_mode = 'ON_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'OFF_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'OFF';
mysql> SET GLOBAL enforce_gtid_consistency = 'OFF';
3) Wyłącz GTID w mysql57b:
mysql> SET GLOBAL gtid_mode = 'ON_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'OFF_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'OFF';
mysql> SET GLOBAL enforce_gtid_consistency = 'OFF';
4) Przywróć kopię zapasową mysqldump na mysql57a:
$ mysql -uroot -p < mysql56a-fullbackup.sql
5) Przywróć kopię zapasową mysqldump na mysql57b:
$ mysql -uroot -p < mysql56a-fullbackup.sql
6) Uruchom skrypt aktualizacji MySQL na mysql57a (aby sprawdzić i zaktualizować wszystkie tabele do aktualnej wersji):
$ mysql_upgrade -uroot -p
7) Uruchom skrypt aktualizacji MySQL na mysql57b (aby sprawdzić i zaktualizować wszystkie tabele do aktualnej wersji):
$ mysql_upgrade -uroot -p
Oba serwery w klastrze podrzędnym są teraz umieszczone w poczekalni z migawką danych ze starego serwera głównego, mysql56a, i są gotowe do replikacji.
Konfigurowanie replikacji dla klastra Slave
1) Zresetuj logi binarne za pomocą RESET MASTER na mysql57a, dzięki czemu nie musimy później określać pliku binarnego i pozycjonowania logów na mysql57b. Ponadto usuwamy wszystkie istniejące odniesienia GTID, które zostały skonfigurowane wcześniej:
mysql> RESET MASTER;
mysql> SET @@global.gtid_purged='';
2) W mysql57a pobierz plik binlog i pozycję z pliku zrzutu, mysql56a-fullbackup.sql:
$ head -100 mysql56a-fullbackup.sql | grep LOG_POS
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000007', MASTER_LOG_POS=4677987;
3) Rozpocznij replikację ze starego mastera mysql56a do nowego mastera mysql57a, podając prawidłowe wartości MASTER_LOG_FILE i MASTER_LOG_POS pobrane w poprzednim kroku. Na mysql57a:
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.10.22', MASTER_USER = 'slave', MASTER_PASSWORD = 'slavepassword', MASTER_LOG_FILE='binlog.000007', MASTER_LOG_POS=4677987;
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
Upewnij się, że widzisz następujące wiersze:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Prawdopodobnie będziesz musiał poczekać, aż mysql57a dogoni mysql56a, monitorując "Seconds_Behind_Master" i upewniając się, że zmienia się na 0.
4) W tym momencie mysql57a replikuje dane z mysql56a, co oznacza, że na serwerze nie ma teraz wszystkich użytkowników utworzonych przez ClusterControl (ponieważ mysql57a śledzi teraz dane z mysql56a). ClusterControl będzie miał problem z połączeniem się z mysql57a i pojawi się jako "w dół". Zasadniczo oznacza to, że ClusterControl nie może połączyć się z serwerami MySQL, ponieważ brakuje grantów. Brakujący użytkownicy to:
- [email protected]
- [email protected]'{wszystkie węzły w jednym konkretnym klastrze}'
- [email protected]'{ClusterControl host}'
Wszystkie poświadczenia są bezpiecznie przechowywane w ClusterControl i samym serwerze bazy danych. Aby odzyskać dane uwierzytelniające z odpowiednich plików, musisz mieć uprawnienia administratora.
Teraz odtwórzmy brakujących użytkowników na nowym masterze, mysql57a:
a) Utwórz użytkownika kopii zapasowej (hasło pobrane z /etc/mysql/secrets-backup.cnf na mysql57a):
mysql> CREATE USER [email protected] IDENTIFIED BY '[email protected]!65%JlNB1z';
mysql> GRANT RELOAD, LOCK TABLES, PROCESS, SUPER, REPLICATION CLIENT ON *.* TO [email protected];
b) Utwórz użytkowników replikacji dla wszystkich hostów DB (hasło pobrane ze zmiennej repl_password w pliku /etc/cmon.d/cmon_X.cnf na serwerze ClusterControl, gdzie X jest identyfikatorem klastra podrzędnego):
mysql> CREATE USER 'rpl_user'@'192.168.10.31' IDENTIFIED BY '68n61F+bdsW1}[email protected]}x5J';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'rpl_user'@'192.168.10.31';
mysql> CREATE USER 'rpl_user'@'192.168.10.32' IDENTIFIED BY '68n61F+bdsW1}[email protected]}x5J';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'rpl_user'@'192.168.10.32';
c) Utwórz dwóch użytkowników bazy danych cmon (jednego dla adresu IP i jednego dla nazwy hosta) do użytku ClusterControl (hasło pobrane ze zmiennej mysql_password w /etc/cmon.d/cmon_X.cnf na serwerze ClusterControl, gdzie X jest identyfikatorem klastra urządzenia podrzędnego klaster):
mysql> CREATE USER [email protected]'192.168.10.19' IDENTIFIED BY 'My&Passw0rd90';
mysql> GRANT ALL PRIVILEGES ON *.* TO [email protected]'192.168.10.19' WITH GRANT OPTION;
mysql> CREATE USER [email protected]'cc.local' IDENTIFIED BY 'My&Passw0rd90';
mysql> GRANT ALL PRIVILEGES ON *.* TO [email protected]'cc.local' WITH GRANT OPTION;
5) W tym momencie mysql57a powinien pojawić się na zielono w ClusterControl. Teraz możemy skonfigurować łącze replikacji z mysql57a do mysql57b. Na mysql57b:
mysql> RESET MASTER;
mysql> SET @@global.gtid_purged='';
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.10.31', MASTER_USER = 'rpl_user', MASTER_PASSWORD = '68n61F+bdsW1}[email protected]}x5J';
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
**Nie musimy określać MASTER_LOG_FILE i MASTER_LOG_POS, ponieważ zawsze zaczyna się od ustalonej pozycji początkowej po RESET MASTER w kroku 1.
Upewnij się, że widzisz następujące linie:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Monitoruj stan replikacji i upewnij się, że mysql57b nadąża za mysql57a, a mysql57a za mysql56a. Może być konieczne włączenie trybu tylko do odczytu na mysql57b (i/lub mysql57a), aby zabezpieczyć się przed przypadkowym zapisem.
mysql> SET GLOBAL super_read_only = 1;
mysql> SET GLOBAL read_only = 1;
W interfejsie użytkownika ClusterControl bieżący stan można zobaczyć w sekcji Przegląd:
W tym momencie nowy master mysql57a, 192.168.10.31 jest replikowany z stary samodzielny host mysql56a, 192.168.10.22, podczas gdy nowy slave mysql57b (tylko do odczytu) replikuje się z mysql57a, 192.168.10.31. Wszystkie węzły są synchronizowane z opóźnieniem replikacji 0.
Alternatywnie możesz zakomentować następujące wiersze w plikach konfiguracyjnych MySQL w sekcji [mysqld]:
#gtid_mode=ON
#enforce_gtid_consistency=1
Włączanie GTID w klastrze podległym
Należy zauważyć, że w przypadku MySQL 5.6 i nowszych ClusterControl nie obsługuje implementacji bez GTID w przypadku niektórych funkcji zarządzania, takich jak Rebuild Replication Slave i Change Replication Master. Tak więc w czasie odcięcia (kiedy kierujesz aplikacje do nowego klastra) z samodzielnego serwera MySQL (mysql56a), zaleca się ponowne włączenie GTID na mysql57a i mysql57b, wykonując następujące czynności:
1) Upewnij się, że funkcja automatycznego odzyskiwania ClusterControl jest wyłączona:
2) Podczas przerwy konserwacyjnej musimy zatrzymać replikację ze starego mastera, mysql56a, usuń całą konfigurację slave na mysql57a i włącz z powrotem GTID. Na mysql57a uruchom następujące polecenia we właściwej kolejności:
mysql> SHOW SLAVE STATUS\G # Make sure you see "Slave has read all relay log"
mysql> STOP SLAVE;
mysql> RESET SLAVE ALL;
mysql> SET GLOBAL super_read_only = 0;
mysql> SET GLOBAL read_only = 0;
mysql> SET GLOBAL gtid_mode = 'OFF_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'ON_PERMISSIVE';
mysql> SET GLOBAL enforce_gtid_consistency = 'ON';
mysql> SET GLOBAL gtid_mode = 'ON';
W tym momencie praktycznie bezpieczne jest dla Twojej aplikacji rozpoczęcie pisania do nowego mastera, mysql57a. Stary samodzielny MySQL jest teraz poza łańcuchem replikacji i można go wyłączyć.
3) Powtórz te same kroki dla mysql57b. Pamiętaj, aby wykonać kroki we właściwej kolejności:
mysql> SHOW SLAVE STATUS\G # Make sure you see "Slave has read all relay log"
mysql> STOP SLAVE;
mysql> RESET SLAVE ALL;
mysql> SET GLOBAL super_read_only = 0;
mysql> SET GLOBAL read_only = 0;
mysql> SET GLOBAL gtid_mode = 'OFF_PERMISSIVE';
mysql> SET GLOBAL gtid_mode = 'ON_PERMISSIVE';
mysql> SET GLOBAL enforce_gtid_consistency = 'ON';
mysql> SET GLOBAL gtid_mode = 'ON';
4) Następnie zresetuj master na nowym master, mysql57a:
mysql> RESET MASTER;
3) Następnie na nowym urządzeniu podrzędnym mysql57b skonfiguruj łącze replikacji za pomocą GTID do mysql57a:
mysql> RESET MASTER;
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.10.31', MASTER_USER = 'rpl_user', MASTER_PASSWORD = '68n61F+bdsW1}[email protected]}x5J', MASTER_AUTO_POSITION = 1;
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
Upewnij się, że pola Retrieved_Gtid_Set i Executed_Gtid_Set mają swoją wartość GTID.
4) W tym momencie przywróciliśmy konfigurację replikacji skonfigurowaną wcześniej przez ClusterControl na etapie wdrażania klastra. Następnie możemy włączyć tryb tylko do odczytu na nowym urządzeniu podrzędnym, mysql57b, aby chronić go przed przypadkowymi zapisami:
mysql> SET GLOBAL super_read_only = 1;
mysql> SET GLOBAL read_only = 1;
Na koniec ponownie włącz automatyczne odzyskiwanie ClusterControl dla klastra, przełączając ikony zasilania na zielone. Następnie możesz zlikwidować starego mastera, mysql56a. Właśnie zakończyliśmy naszą migrację online z MySQL 5.6 do MySQL 5.7 z minimalnym przestojem. Podobne kroki powinny również działać w przypadku migracji do MySQL 8.0.