Menu
Szybki wybór
Hosting Domeny VPS SSL Kalkulator Porównania FAQ
Aktywne kody
Wszystkie kody rabatowe

MySQL replikacja — konfiguracja master-replica

Opublikowano: 9 kwietnia 2026 · Kategoria: Bazy danych

Replikacja MySQL pozwala automatycznie kopiować dane z serwera master na jeden lub więcej serwerów replica (slave). Zastosowania: wysoka dostępność (HA) — replica przejmuje ruch gdy master padnie, skalowanie odczytu — aplikacja czyta z replik, odciążając mastera, a także backupy bez obciążenia produkcji. Ten artykuł przeprowadzi Cię przez konfigurację od zera.

Po co replikacja — trzy główne zastosowania

  • Wysoka dostępność (HA) — gdy master padnie, możesz ręcznie lub automatycznie (MHA, Orchestrator) promować replikę na nowego mastera. Czas przestoju: minuty zamiast godzin.
  • Skalowanie odczytu (Read Scaling) — zapytania SELECT (raporty, listy, API read-only) kieruj na repliki. Master obsługuje tylko zapisy. Dzięki temu jeden zapis generuje dane dla wielu replik obsługujących ruch odczytowy.
  • Backupy bez blokowania produkcjimysqldump na replice nie obciąża mastera. Replika może być tymczasowo zatrzymana (STOP REPLICA SQL_THREAD) dla spójnego dumpa.

Typy replikacji: statement vs row vs mixed

Typ Co zapisuje w binlog Zalety Wady
Statement (SBR) Oryginalne zapytanie SQL Mały rozmiar logów Niebezpieczny dla NOW(), RAND(), UUID()
Row (RBR) Zmienione wiersze (before/after) Deterministyczny, bezpieczny Duże logi przy masowych UPDATE
Mixed SBR gdy bezpieczne, RBR gdy konieczne Kompromis Trudniejsza analiza logów

MySQL 8+ domyślnie używa Row-based replication — jest bezpieczniejszy i zalecany dla nowych instalacji.

Konfiguracja mastera — my.cnf

Na serwerze master edytuj /etc/mysql/mysql.conf.d/mysqld.cnf (lub /etc/my.cnf):

[mysqld]
# Unikalny identyfikator serwera w topologii replikacji (1 = master)
server-id = 1

# Włącz binary log — WYMAGANE dla replikacji
log_bin = /var/log/mysql/mysql-bin.log

# Format replikacji (row jest domyślny i zalecany w MySQL 8+)
binlog_format = ROW

# Opcjonalnie: replikuj tylko konkretne bazy
# binlog_do_db = moja_baza
# binlog_ignore_db = information_schema

# Czas przechowywania binary logów (sekundy) — 7 dni
binlog_expire_logs_seconds = 604800

# Synchronizacja dysku po każdym commicie (bezpieczniej, wolniej)
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
sudo systemctl restart mysql

# Sprawdź czy binary log działa
mysql -u root -p -e "SHOW MASTER STATUS\G"

Zapamiętaj wartości File i Position z SHOW MASTER STATUS — będą potrzebne przy konfiguracji repliki.

Tworzenie użytkownika replikacji

-- Na masterze: utwórz dedykowanego użytkownika dla repliki
mysql -u root -p

CREATE USER 'replika_user'@'10.0.0.11' IDENTIFIED WITH mysql_native_password BY 'BezpieczneHaslo123!';
GRANT REPLICATION SLAVE ON *.* TO 'replika_user'@'10.0.0.11';
FLUSH PRIVILEGES;

-- Zrób dump bazy z pozycją binary logu (dla pierwszej synchronizacji)
-- Opcja 1: zablokuj zapisy na czas dumpa
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;   -- zanotuj File i Position!

-- W osobnej sesji (lub po zanotowaniu pozycji):
mysqldump -u root -p --all-databases --master-data=2 > /tmp/dump.sql

-- Odblokuj
UNLOCK TABLES;

Konfiguracja repliki — my.cnf i CHANGE REPLICATION SOURCE

# /etc/mysql/mysql.conf.d/mysqld.cnf na REPLICE
[mysqld]
# Unikalny ID — inny niż master
server-id = 2

# Replika nie musi mieć binary logu (chyba że to kaskadowa replikacja)
# log_bin = ...

# Zabezpieczenie — replika nie przyjmuje zapisów bezpośrednio
super_read_only = ON

# Opcjonalnie: relay log
relay_log = /var/log/mysql/mysql-relay-bin.log
sudo systemctl restart mysql

# Zaimportuj dump z mastera
mysql -u root -p < /tmp/dump.sql

# Skonfiguruj połączenie z masterem
mysql -u root -p

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '10.0.0.10',
  SOURCE_USER = 'replika_user',
  SOURCE_PASSWORD = 'BezpieczneHaslo123!',
  SOURCE_LOG_FILE = 'mysql-bin.000001',   -- z SHOW MASTER STATUS
  SOURCE_LOG_POS = 1234;                  -- z SHOW MASTER STATUS

START REPLICA;

-- Sprawdź status replikacji
SHOW REPLICA STATUS\G

SHOW REPLICA STATUS — interpretacja kluczowych pól

Pole Oczekiwana wartość Co oznacza problem
Replica_IO_Running Yes No — problem z połączeniem do mastera (hasło, firewall, sieć)
Replica_SQL_Running Yes No — błąd SQL przy odtwarzaniu (duplikat klucza, brakująca tabela)
Seconds_Behind_Source 0 lub bliskie 0 Duże wartości = replika nie nadąża za masterem
Last_SQL_Error puste Komunikat błędu SQL — napraw lub pomiń
Last_IO_Error puste Błąd połączenia — sprawdź dostęp sieciowy i credentials

Replikacja GTID — lepsza alternatywa

GTID (Global Transaction Identifier) eliminuje potrzebę ręcznego podawania pozycji w binary logu. Każda transakcja ma unikalny ID, replika wie skąd kontynuować po restarcie lub failoverze.

# Na masterze I replice (my.cnf):
[mysqld]
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON   # replikuje GTID do binary logu repliki

# Na replice — CHANGE SOURCE bez podawania pozycji:
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '10.0.0.10',
  SOURCE_USER = 'replika_user',
  SOURCE_PASSWORD = 'BezpieczneHaslo123!',
  SOURCE_AUTO_POSITION = 1;   -- GTID: replika sama znajdzie pozycję

START REPLICA;
SHOW REPLICA STATUS\G         -- sprawdź Executed_Gtid_Set

Przy GTID: super_read_only = ON na replice jest krytyczne — zapobiegnie przypadkowym zapisom które złamałyby sekwencję GTID i wymagały reiniicjalizacji replikacji.

Typowe błędy i jak je naprawić

# Błąd: Duplicate entry 'X' for key 'PRIMARY' (Error 1062)
# Przyczyna: wiersz już istnieje na replice (rozbieżność danych)
# Rozwiązanie tymczasowe (pomiń jeden błąd):
STOP REPLICA;
SET GLOBAL sql_replica_skip_counter = 1;
START REPLICA;
-- Lepiej: reinicjalizuj replikację lub napraw dane ręcznie

# Błąd: Access denied for user 'replika_user'@'10.0.0.11'
# Sprawdź na masterze:
SELECT user, host FROM mysql.user WHERE user = 'replika_user';
SHOW GRANTS FOR 'replika_user'@'10.0.0.11';

# Błąd: Slave_IO_Running: Connecting (nie Yes)
# Sprawdź czy port 3306 jest dostępny z repliki:
# mysql -h 10.0.0.10 -u replika_user -p (z serwera repliki)
# Sprawdź firewall: ufw allow from 10.0.0.11 to any port 3306

Najczęstsze pytania

Czym różni się replikacja statement-based od row-based? +
Statement-based replication (SBR) zapisuje w binary logu oryginalne zapytania SQL (INSERT, UPDATE, DELETE). Row-based replication (RBR) zapisuje faktycznie zmienione wiersze. SBR jest bardziej zwięzły dla zapytań modyfikujących wiele wierszy jednym UPDATE, ale niebezpieczny przy funkcjach niedeterministycznych (NOW(), RAND(), UUID()) — replika może dostać inny wynik niż master. RBR jest bezpieczniejszy i domyślny w MySQL 8+, ale generuje więcej danych w binarnym logu. Mixed (domyślnie przed MySQL 8) używa SBR gdy to bezpieczne, RBR gdy konieczne.
Jak długo może trwać lag replikacji (Seconds_Behind_Source)? +
Seconds_Behind_Source powinien być bliski 0 przy normalnym obciążeniu. Lag wzrasta gdy: (1) master ma dużo zapisów a replika nie nadąża z ich odtwarzaniem — rozwiązanie: parallel replication (slave_parallel_workers &gt; 1), (2) replika wykonuje wolne zapytania (blokady) — sprawdź SHOW PROCESSLIST na replice, (3) długie transakcje na masterze — replika czeka na ich zakończenie. Przy lag &gt; 60s backupy z repliki mogą mieć nieaktualne dane.
Czym jest GTID i dlaczego jest lepszy niż replikacja pozycyjna? +
GTID (Global Transaction ID) to unikalny identyfikator każdej transakcji w formacie uuid:sequence_number. Replika śledzi GTID zamiast pozycji w binary logu (file:position). Korzyści: (1) Po failoverze nowa replika automatycznie wie od której transakcji zacząć synchronizację — nie trzeba ręcznie szukać pozycji w logu. (2) Łatwiejszy failover i rekonfiguracja topologii replikacji. (3) Narzędzia jak pt-slave-restart lepiej radzą sobie z błędami. Wada: wymaga włączenia gtid_mode=ON na wszystkich węzłach jednocześnie.
Jak zresetować błędną replikację bez utraty danych? +
Gdy SHOW REPLICA STATUS pokazuje błąd (Last_SQL_Errno): (1) Sprawdź treść błędu (Last_SQL_Error) — czy to problem z duplikowanym kluczem, brakującą tabelą itp. (2) Jeśli błąd można pominąć bezpiecznie: STOP REPLICA; SET GLOBAL sql_replica_skip_counter = 1; START REPLICA; (3) Lepiej: napraw przyczynę (np. wstaw brakujący wiersz na replice), a potem START REPLICA. (4) Przy replikacji GTID: możesz pominąć konkretny GTID przez SET GTID_NEXT = "uuid:N"; BEGIN; COMMIT; SET GTID_NEXT = "AUTOMATIC";. Nigdy nie pomijaj błędów produkcyjnych blindly — mogą oznaczać rozbieżność danych.

Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.