Podstawowy schemat przepływu plików replikacji master-slave (master-master będzie lustrzany) będzie następujący:
- Slave łączy się z masterem
- Wątek I/O pyta o dane
- Wątek Binlog dump na masterze wysyła zawartość do wątku I/O
- Wątek SQL zatwierdza dane (zmiany)
Poniżej krótko opiszę jak zestawić replikację master-master dla MySQL v.5.5 w następujących krokach:
- Konfiguracja serwerów - plik my5.5.cnf
- Instalacja serwera MySQL v5.5
- Ustawienie replikacji
Serwery bazodanowe będą stać pod adresami:
- 192.168.100.167 - server ID = 1
- 192.168.100.166 - server ID = 2
Konfiguracja MySQL'a (my5.5.cnf)
Chce aby klient łączył się na porcie 3309 przy kodowaniu utf8. Wskazałam także ścieżkę do socket-u:[client] port = 3309 socket = /tmp/mysql5.5.sock default-character-set = utf8
Ustawienia serwera:
[mysqld] user = mysql skip-name-resolve innodb_file_per_table skip-external-locking report-port = 3309 tmpdir = /home/mysql/mysql5.5/mysqltmp event_scheduler = 0 pid-file = /home/mysql/mysql5.5/mysql.pid socket = /tmp/mysql5.5.sock datadir = /home/mysql/mysql5.5/myisam port = 3309 server-id = 1 character-set-server = utf8 auto_increment_offset = 1 auto_increment_increment = 2 log-output = file general_log = 1 general_log_file = /home/mysql/mysql5.5/log/mysql.log log_error = /home/mysql/mysql5.5/log/mysql.err log-warnings = 1 long_query_time = 1 slow_query_log = 1 slow_query_log_file = /home/mysql/mysql5.5/slow.log log_queries_not_using_indexes = 1 log-bin = /home/mysql/mysql5.5/replication/binlog binlog-format = ROW relay-log = /home/mysql/mysql5.5/replication/relay-bin #default-table-type = InnoDB innodb_data_home_dir = /home/mysql/mysql5.5/innodb/ innodb_data_file_path = ibdata/ibdata1:50M:autoextend innodb_log_group_home_dir = /home/mysql/mysql5.5/innodb/iblogs innodb_flush_log_at_trx_commit = 2 innodb_fast_shutdown
Z ustawień serwera przeczytamy, że:
- nasłuchuję na porcie 3309, jest to także port dla połączenia ze slavem
- logi bazodanowe możemy znaleźć w katalogu: /home/mysql/mysql5.5/log
- slow logi są pod ścieżką: /home/mysql/mysql5.5/slow.log
- katalog dla tabel tymczasowych jest pod ścieżką: /home/mysql/mysql5.5/mysqltmp
- każdy z serwerów podpiętych do replikacji musi mieć unikalną wartość dla server-id, w tym przypadku jest ustawione na 1
- dla replikacji master-master musimy dobrze ustawić zmienne odpowiadające za kontrolowanie auto incrementów kluczy głównych. Zmienna auto_increment_increment mówi jak mają być zmieniane wartość, a auto_increment_offset od jakiej wartości zaczynamy. Dla dwóch serwerów w replikacji master-master ustawimy, że wartości mają się zmieniać co 2 zaczynając od 1 dla serwera ID 1 i zaczynając od 2 dla serwera ID 2
- dla enginu InnoDB będziemy przechowywać dane w katalogu: /home/mysql/mysql5.5/innodb. Przed uruchomieniem serwera stworzymy podkatalogi:
- ibdata -pod zmienną innodb_data_file_path znajdziecie ścieżkę do plików danych związanych z tym enginem odraz ich rozmiar. Pełna ścieżka do tego katalogu jest zapisana pod zmienną innodb_data_home_dir.
- iblogs -katalog, do którego ścieżka została zdefiniowana przez zmienną innodb_log_group_home_dir. Przechowane są tam redo log-i, czyli struktury danych na dysku używane w czasie odzyskiwania danych po niespodziewanym zamknięciu serwera aby odzyskać poprawnie zapisane dane przy niedokończonych transakcjach.
- pliki dla replikacji, które można znaleźć w katalogu /home/mysql/mysql5.5/replication/ pod nazwami zaczynającymi się od:
- binlog - pliki binlogów, które zawierają informację o numerze pliku, zdarzenia o zmianach w bazie danych i plik indexu z listą wszystkich używanych plików
- relay-bin - składa się ze zdarzeń odczytywanych z binary logów z mastera i zapisanych przez wątek I/O slav-a. Zdarzenia w tych plikach są wykonywane na slave jako część wątku SQL.
- typ replikacji (w tym przypadku ROW):
- ROW - master wysyła zdarzenia, które identyfikują indywidualne zmiany wierszy które zostały dokonane
- STATEMENT - replikowane są zapytania SQL (dla naszej wersji serwera jest to domyślna opcja)
- MIXED - połączenie dwóch poprzednich typów replikacji.
- zmienna innodb_file_per_table - jest włączona aby dla każdej tabeli, dane i index-y były w oddzielnych plikach.
Instalacja serwera MySQL 5.5
Przed rozpoczęciem instalacji, pobrałam wybraną przeze mnie wersję serwera ze storny http://downloads.mysql.com/archives/community/. Po rozpakowaniu pliku tar.gz znajdziecie plik INSTALL-BINARY, w których opisany jest proces instalacji, dlatego tylko krótko przedstawię swoje kroki instalacji.W pierwszej kolejności dodaję grupy i użytkownika mysql (jeśli jeszcze nie istnieje). W lokalizacji /usr/local rozpakowuje plik z serwerem, a następnie stworzony katalog podlinkuje pod symlinka mysql5.5.
sudo groupadd mysql sudo useradd -g mysql mysql cd /usr/local sudo gunzip < /home/ela/mysql/mysql-5.5.23-linux2.6-x86_64.tar.gz | sudo tar xvf - sudo ln -s /usr/local/mysql-5.5.23-linux2.6-x86_64.tar.gz mysql5.5
Domyślnie mysql szuka pliku konfiguracyjnego w katalogu /etc. Na tej maszynie istnieje już działający serwer MySQL, dlatego nasz plik konfiguracyjny będzie można znaleźć pod /etc/my5.5.cnf
cd mysql5.5 sudo chown -R mysql . sudo chgrp -R mysql . sudo cp /home/ela/mysql/my.cnf /etc/my5.5.cnf
Po zainstalowaniu plików serwera, musimy zainicjować katalog z danymi i stworzyć system tabel. Ponieważ mamy niestandardowe ścieżki, musimy je podać:
sudo scripts/mysql_install_db --defaults-file=/etc/my5.5.cnf --user=mysql --builddir=/usr/local/mysql5.5/bin --pid-file=/home/mysql/mysql5.5/mysql.pid sudo chown -R root .
Uruchamiamy zainstalowany serwer i jeśli wszystko zakończy się dobrze, musimy stworzyć super użytkownika, któremu nadamy hasło:
bin/mysqld_safe --defaults-file=/etc/my5.5.cnf --user=mysql --ledir=/usr/local/mysql5.5/bin --pid-file=/home/mysql/mysql5.5/mysql.pid & ./bin/mysqladmin -u root password 'root' --host=127.0.0.1 --port=3309
Ustawienie replikacji
Ponieważ dopiero co zainstalowaliśmy nasze serwery, nie ma potrzeby ich wyrównywać. W przeciwnym przypadku musieli byśmy zrobić dump serwera i zrestować dane na drugim serwerze.Aby replikacja mogła działać, na każdym z serwerów stworzymy użytkownika z prawami do replikacji:
CREATE USER 'replication'@'%' IDENTIFIED BY 'replication'; GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';
Jeśli na masterze mamy dane, które chcemy synchronizować przed uruchomieniem replikacji, musimy zatrzymać działające zapytania na masterze aby otrzymać aktualne binary logi, zdumpować je, zrestartować na slave i pozwolić na kontynuowanie działania przerwanych zapytań (Polecenie na masterze: UNLOCK TABLES).
Aktualne binlogi otrzymamy przez zapytanie:
FLUSH TABLES WITH READ LOCK;
Sprawdzamy jaki jest status binary logów (nazwa i pozycja) dla serwerów (poniżej przykład wyniku dla serwera ID 1) aby sprawdzić od którego pliku i jakiej pozycji ma się rozpocząć replikacja:
mysql (root@(none))> show master status; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | binlog.000003 | 502 | | | +---------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
Ustawiamy parametry replikacji na każdym masterze (Szczegóły w dokumentacji: http://dev.mysql.com/doc/refman/5.5/en/change-master-to.html lub http://dev.mysql.com/doc/refman/5.5/en/replication-howto-slaveinit.html).
Dla serwera ID 1 (192.168.100.167):
mysql (root@(none))>CHANGE MASTER TO MASTER_HOST='192.168.100.166', MASTER_PORT=3309, MASTER_USER='replication', MASTER_PASSWORD='replication', MASTER_LOG_FILE='binlog.000005', MASTER_LOG_POS=107;
Dla serwera ID 2 (192.168.100.166):
mysql (root@(none))>CHANGE MASTER TO MASTER_HOST='192.168.100.167', MASTER_PORT=3309, MASTER_USER='replication', MASTER_PASSWORD='replication', MASTER_LOG_FILE='binlog.000003', MASTER_LOG_POS=502;
Uruchamiany replikację na każdym serwerze:
mysql (root@(none))> SLAVE START;
Status slave z servera id 1 (192.168.100.167) weryfikuję:
mysql (root@(none))> SHOW slave STATUS \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.100.166 Master_User: replication Master_Port: 3309 Connect_Retry: 60 Master_Log_File: binlog.000005 Read_Master_Log_Pos: 107 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 250 Relay_Master_Log_File: binlog.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 107 Relay_Log_Space: 400 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 1 row in set (0.00 sec)
Status slave z servera id 2 (192.168.100.166) weryfikuję:
mysql (root@(none))> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.100.167 Master_User: replication Master_Port: 3309 Connect_Retry: 60 Master_Log_File: binlog.000003 Read_Master_Log_Pos: 502 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 250 Relay_Master_Log_File: binlog.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 502 Relay_Log_Space: 400 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec)
Mam nadzieję, że Wam także się udało. Przy pomocy stworzonej replikacji będę chciała sprawdzać kilka rzeczy, które mogą się przyda wiedzieć dla programisty. Ale to do następnego posta.
" pozwolić na kontynuowanie działania przerwanych zapytań (Polecenie na masterze: UNLOCK TABLES)."
OdpowiedzUsuńPo zatrzymaniu na master binlogów wykonaniu dumpa i zaimportowaniu na slavie dodaniu danych odnośnie binloga i pozycj nie musimy wykonywać unlock tables; na master. Po uruchomieniu start slave; na slavie, pozycja na master zacznie się zmieniać sama.
Dodatkowo polecany jest jednak dump master z master-data= ponieważ to daje gwarancje aktualnych zmian w binlogu.
Usuń