Introducere
Replicarea permite sincronizarea / copierea datelor de pe un server de baze de date central (master), pe unul sau mai multe servere de baze de date secundare (slave / replica). Procesul este disponibil si la nivelul serverelor de baze de date de tip MySQL. Replicarea poate avea in vedere toate colectiile de date de pe un server, anumite baze de date sau chiar tabele de la nivelul unei baze de date.
In mod implicit, procesul de replicare a datelor este unul de tip asincron, adica masinile de tip slave nu trebuie sa fie in permanenta conectate pentru a primi actualizari de la serverul de tip master. Avantajul acestei abordari il reprezinta posibilitatea amplasarii serverelor secundare la distante mari, unde conexiunea poate fi lenta sau disponibila doar in anumite momente de timp.
Principalele avantaje ale utilizarii replicarii datelor includ:
• load balancing si scale-out: distributia cererilor de la un server de baze de date catre mai multe astfel de sisteme, pentru a imbunatatii performantele; in acest scenariu, toate modificarile se realizeaza doar pe serverul de tip master, in timp ce citirile au in vedere mai multe servere secundare; aceasta arhitectura creste performantele la scriere, deoarece serverul central este dedicat pentru manipularea datelor, iar viteza de citire creste cu fiecare nou server secundar adaugat in retea;
• securitate datelor: deoarece datele sunt replicate pe serverele secundare, si sincronizarea acestora cu serverul master poate fi suspendata, pot fi rulate proceduri de back-up pe serverele secundare, fara a influenta serverul central;
• analiza date: la nivelul unui server secundar pot fi rulate proceduri de analiza a datelor, fara a afecta performatele serverului master;
• distributie date: replicarea datelor poate fi utilizata pentru a crea copii locale ale datelor, fara a beneficia de acces permanent la serverul central.
Serverul MySQL ofera suport pentru diferite metode de replicare. Metoda traditionala necesita sincronizarea fisierelor de tip log si a pozitilor din cadrul acestor fisiere intre serverul central si cele secundare. O alta metoda, mai noua, are la baza identificatorii de tranzactii globali (GTID), este de tip tranzactional si nu necesita lucrul cu fisiere de tip log. Utilizand metoda GTID de replicare a datelor poate fi asigurata consistenta dintre serverul central si cele secundare, atata timp cat toate tranzactiile finalizate la nivelul sursei vor fi rulate si la nivelul replicilor.
Sistemele de tip MySQL ofera suport si pentru diferite tipuri de sincronizare. Versiunea asincrona, unidirectionala, are la baza un server sursa si unul sau mai multe servere secundare, de tip replica. Replicarea asincrona presupune realizarea urmatoarelor actiuni: instructiunile de definire si manipulare a datelor, care sunt rulate la nivelul serverului de tip master, se inregistreaza intr-un fisier de tip log binar (binary log); serverele de tip slave citesc acest jurnal si salveaza elementele de la nivelul lui in alte fisire log (relay log) prin intermediul IO thread; executia efectiva a instructiunilor pentru a reproduce datele este gestionata secvential de catre SQL thread. Nu exisa garantia sincronizarii serverelor secundare, cu serverul de tip master.
Replicarea sincrona este o caracteristica a MySQL NDB Cluster. In replicarea sincrona, dupa finalizarea unei tranzactii pe serverul central, este asteptata sincronizarea modificarilor la nivelul tuturor serverelor secundare.
In MySQL este disponibila si replicarea semi-sincrona, care presupune faptul ca dupa finalizarea unei tranzactii la nivelul serverului central se asteapta pana cand cel putin un server secundar confirma ca a primit si a inregistrat evenimentele corespunzatoare tranzactiei. Astfel, scade posibilitatea de a pierde tranzactii finalizate, la aparitia unor defectiuni hardware. Scade insa si performanta sistemului, datorita cresterii timpului de executie a tranzactiei, cel putin cu timpul necesar comunicarii intre cele doua servere.
Formate de replicare
Procesul de replicare a datelor are la baza replicarea evenimentelor de la nivelul unui log binar ce este disponibil pe serverul central. Aceste evenimente sunt citite si procesate pe fiecare server secundar. Evenimentele sunt inregistrate in log-ul binar in diferite formate specifice pentru tipul respectivului eveniment. Formatele de replicare corespund modului de inregistrare a evenimentelor in log-ul binar.
In sistemele de tip MySQL pot fi utilizate trei formate de replicare:
• statement-based (SBR): in acest caz in log-ul binar sunt inregistrate instructiuni SQL care permit manipularea datelor; replicarea se realizeaza prin rularea acestor instructiuni SQL pe serverul de tip slave;
• row-based (RBR): sunt replicate doar inregistrarile care au fost actualizate pe serverul central; replicarea pe baza inregistrarilor reprezinta formatul implicit utilizat la nivelul sistemelor de tip MySQL;
• mixed-based (MBR): decizia cu privire la formatul utilizat pentru fisierul de tip log binar depinde de modificarea care este inregistrata; in marea majoritate a cazurilor este utilizat formatul SBR; in functie de tipul instructiunilor si motorul de stocare utilizat, pentru fisierul de tip log se utilizeaza formatul RBR.
Variabila de sistem binlog_format stabileste formatul de inregistrare utilizat pe un server MySQL. Pentru stabilirea valorii acestei variabile, la nivel global sau de sesiune, este necesar unul din privilegiile SYSTEM_VARIABLE_ADMIN sau SUPER.
Activare inregistrare binara
Pentru implemnetarea unui proces de replicare, in primul rand trebuie activat procesul de inregistrare in log-ul binar (binary log) de la nivelul serverului de tip master. Acest aspect poate fi realizat prin setarea optiunilor de configurare log_bin si server_id, si repornirea serverului. Daca la nivelul fisierului de configurare se precizeaza optiunea de configurare log_bin fara o valoare, atunci fisierele de tip log binar sunt create direct in directorul de date.
root@master1:/# pico /etc/mysql/my.cnf
[mysqld] log_bin = /var/lib/mysql/binlogs/master1 server_id = 101
root@master1:/# mkdir -p /var/lib/mysql/binlogs root@master1:/# chown -R mysql:mysql /var/lib/mysql/binlogs root@master1:/# sudo systemctl restart mysql
Variabila log_bin precizeaza calea si formatul pentru fisierele de tip log. De exemplu daca variabila este setata la valoarea /var/log/mysql/binlogs/master1, fisierele de tip log vor fi stocate la nivelul directorului /var/log/mysql/binlogs si vor avea denumiri de tipul master1.000001, master1.000002, si asa mai departe.
mysql> SHOW VARIABLES LIKE 'log_bin%'; +---------------------------------+--------------------------------------+ | Variable_name | Value | +---------------------------------+--------------------------------------+ | log_bin | ON | | log_bin_basename | /var/lib/mysql/binlogs/master1 | | log_bin_index | /var/lib/mysql/binlogs/master1.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+--------------------------------------+ 5 rows in set (0.00 sec)
Serverul de baze de date creaza un nou fisier de tip log, la pornire, la curatarea fisierelor, sau cand dimensiunea acestora o depaseste pe cea stabilita in variabila de server max_binlog_size. Pentru a lista fisierele de tip log binar de pe un server poate fi utilizata una din urmatoarele doua instructiuni: SHOW MASTER LOGS, respectiv SHOW BINARY LOGS.
mysql> SHOW MASTER LOGS; +----------------+-----------+-----------+ | Log_name | File_size | Encrypted | +----------------+-----------+-----------+ | master1.000001 | 156 | No | +----------------+-----------+-----------+ 1 row in set (0.00 sec)
mysql> SHOW BINARY LOGS; +----------------+-----------+-----------+ | Log_name | File_size | Encrypted | +----------------+-----------+-----------+ | master1.000001 | 156 | No | +----------------+-----------+-----------+ 1 row in set (0.00 sec)
Serverul de baze de date pastreaza in directorul in care sunt stocate fisierele de tip log binar (binary log) si un fisier index, ce contine locatia fiecarui fiser de tip log binar.
root@master1:/# ls -lha /var/lib/mysql/binlogs total 16K drwxr-xr-x 2 mysql mysql 4.0K Apr 26 06:43 . drwxr-x--- 7 mysql mysql 4.0K Apr 26 06:42 .. -rw-r----- 1 mysql mysql 156 Apr 26 06:43 master1.000001 -rw-r----- 1 mysql mysql 38 Apr 26 06:43 master1.index
Replicare master-slave
Replicarea traditionala are in vedere utilizarea unui server de tip master si a unuia sau mai multor servere de tip slave. Versiunea simplificata a acestei arhitecturi cuprinde un singur server master si un singur server slave.
Pentru aceasta arhitectura, procesul de replicare debuteaza la nivelul serverului de tip master cu verificarea activarii inregistrarii binare si a identificatorului serverului. In sectiunea de configurare specifica serverului, din fisierul de configurare global, se verifica valorile pentru optiunile de configurare server_id si log_bin. Optiunea server_id stocheaza identificatorul serverului, adica o valoare intreaga cuprinsa intre 1 si 232-1. Aceasta valoare este unica pentru fiecare server prezent intr-o arhitectura de replicare.
root@master1:/# pico /etc/mysql/my.cnf
[mysqld] log_bin = /var/lib/mysql/binlogs/master1 server_id = 101
Pentru a putea citi log-ul binar, serverele de tip slave necesita prezenta pe serverul de tip master a unui utilizator care detine privilegiul REPLICATION SLAVE. Crearea unui astfel de utilizator si acordarea privilegilor necesare se realizeaza cu ajutorul urmatoarelor instructiuni SQL:
master1> CREATE USER 'replicate'@'%' -> IDENTIFIED WITH mysql_native_password BY '*****'; Query OK, 0 rows affected (0.02 sec) master1> GRANT REPLICATION SLAVE -> ON *.* -> TO 'replicate'@'%'; Query OK, 0 rows affected (0.00 sec)
Si pentru serverele secundare (slave) este necesara stabilirea unor identificarori unici la nivelul arhitecturii, folosind optiunea de configurare server_id sau variabila de sistem cu acelasi nume.
slave1> SET @@GLOBAL.SERVER_ID = 201; Query OK, 0 rows affected (0.00 sec) slave1> SHOW GLOBAL VARIABLES -> WHERE `Variable_name`='server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 201 | +---------------+-------+ 1 row in set (0.01 sec)
Serverele secundare nu necesita activarea inregistrarii binare. Mai mult, prin precizarea optiunii de configurare disable_log_bin fara valoare, este posibila dezactivarea inregistrarii binare.
root@slave1:/# pico /etc/mysql/my.cnf
[mysqld] server_id = 201 disable_log_bin
root@slave1:/# sudo systemctl restart mysql
Dupa repornirea serverului secundar, pot fi verificate valorile ce corespund variabilelor de sistem care au legatura cu inregistrarea binara. Se poate observa ca inregistrarea binara nu este activata, respectiv variabila de sistem log_bin prezinta valoarea OFF.
slave1> SHOW VARIABLES LIKE 'log_bin%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | log_bin | OFF | | log_bin_basename | | | log_bin_index | | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+-------+ 5 rows in set (0.00 sec)
Daca exista date pe serverul central, trebuie realizate copii de siguranta ale bazelor de date folosind utilitarul mysqldump. In astfel de situatii, se recomanda utilizarea parametrului –master-data pentru utilitarul mysqldump, pentru a permite setarea corecta a serverului secundar la importul fisierului copie de siguranta.
root@master1:~/tmp# mysqldump -p --all-databases --routines --events --single-transaction --master-data > master-dump.sql Enter password:
root@master1:~/tmp# ls -lha total 4.4M drwxr-xr-x 2 root root 4.0K Apr 27 03:42 . drwx------ 6 root root 4.0K Apr 26 20:37 .. -rw-r--r-- 1 root root 4.4M Apr 27 03:39 master-dump.sql
Parametrul –master-data determina includerea in fisierul dump a unei comenzi CHANGE REPLICATION SOURCE TO (pentru versiuni MySQL mai mari de 8.0.23) sau CHANGE MASTER TO (pentru versiuni MySQL anterioare 8.0.23), care indica coordonatele log-ului binar, adica numele si pozitia fisierului de tip log. Aceste coordonate corespund serverului de tip master si reprezinta punctul de la care serverele secundare pot incepe replicarea, dupa restaurarea datelor din fisierul copie de siguranta.
Dupa transferul fisierului dump intre serverul de tip master si serverele secundare, poate fi realizata restaurarea acestuia pe serverele de tip slave.
root@slave1:~/tmp# ls -lha total 4.4M drwxr-xr-x 2 root root 4.0K Apr 27 04:13 . drwx------ 7 root root 4.0K Apr 27 04:13 .. -rw-r--r-- 1 root root 4.4M Apr 27 04:11 master-dump.sql
root@slave1:~/tmp# mysql -p -f < master-dump.sql Enter password:
Pentru a configura replicarea intre un server de tip master si un server secundar, pe serverul de tip slave trebuie rulata instructiunea CHANGE REPLICATION SOURCE TO (CHANGE MASTER TO, pentru versiuni MySQL anterioare 8.0.23) cu urmatorii parametri.
slave1> CHANGE REPLICATION SOURCE TO -> SOURCE_HOST='39.36.139.50', -> SOURCE_USER='replicate', -> SOURCE_PASSWORD='*****', -> SOURCE_LOG_FILE='master1.000003', -> SOURCE_LOG_POS=156; Query OK, 0 rows affected, 2 warnings (0.04 sec)
O prima modalitate de obtinere a valorile corespunzatoare clauzelor SOURCE_LOG_FILE si SOURCE_LOG_POS o reprezinta rularea unei comenzi SHOW MASTER STATUS pe serverul de tip master.
master1> SHOW MASTER STATUS; +----------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +----------------+----------+--------------+------------------+-------------------+ | master1.000003 | 156 | | | | +----------------+----------+--------------+------------------+-------------------+ 1 row in set (0.01 sec)
Valorile corespunzatoare clauzelor SOURCE_LOG_FILE si SOURCE_LOG_POS se gasesc si la nivelul fisierului copie de siguranta (master-dump.sql), de unde pot fi preluate pentru comanda CHANGE REPLICATION SOURCE TO.
-- -- Position to start replication or point-in-time recovery from -- CHANGE MASTER TO MASTER_LOG_FILE='master1.000003', MASTER_LOG_POS=156;
Pornirea efectiva a procesului de replicare pe un server secundar se realizeaza cu ajutorul comenzii START REPLICA (START SLAVE, pentru versiuni MySQL anterioare 8.0.23).
slave1> START REPLICA; Query OK, 0 rows affected (0.00 sec)
Pentru a vizualiza informatiile corespunzatoare unuia din serverele replica (slave) pot fi utilizate comenzi de tip SHOW REPLICA STATUS (SHOW SLAVE STATUS, pentru versiuni MySQL anterioare 8.0.23).
slave1> SHOW REPLICA STATUS\G *************************** 1. row *************************** Replica_IO_State: Waiting for master to send event Source_Host: 34.76.189.50 Source_User: replicate Source_Port: 3306 Connect_Retry: 60 Source_Log_File: master1.000004 Read_Source_Log_Pos: 156 Relay_Log_File: slave1-relay-bin.000004 Relay_Log_Pos: 367 Relay_Source_Log_File: master1.000004 Replica_IO_Running: Yes Replica_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_Source_Log_Pos: 776 Relay_Log_Space: 2383 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Source_SSL_Allowed: No Source_SSL_CA_File: Source_SSL_CA_Path: Source_SSL_Cert: Source_SSL_Cipher: Source_SSL_Key: Seconds_Behind_Source: 0 Source_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Source_Server_Id: 101 Source_UUID: fe2eaf6e-7d69-11eb-b590-42010a840005 Source_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Replica_SQL_Running_State: Slave has read all relay log; waiting for more updates Source_Retry_Count: 86400 Source_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Source_SSL_Crl: Source_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Source_TLS_Version: Source_public_key_path: Get_Source_public_key: 0 Network_Namespace: 1 row in set (0.00 sec)
Pasii necesari pentru implementarea unei arhitecturi de tip master-slave pot fi sintetizati astfel:
1. Activare inregistrare binara pe serverul master.
2. Creare utilizator replicare pe serverul master.
3. Configurare identificator server_id pe serverul slave.
4. Realizare copie de siguranta la nivelul serverului master.
5. Restaurare date din copia de siguranta pe serverul slave.
6. Rulare comanda CHANGE REPLICATION SOURCE TO / CHANGE MASTER TO la nivelul serverului slave.
7. Pornire replicare pe serverul slave.
Orice actualizare realizata la nivelul uneia din bazele de date de pe serverul de tip master va fi vizibila si la nivelul serverelor replica. De exemplu, pentru a introduce o noua inregistrare in tabelul actor din baza de date sakila, este necesara rularea urmatoarei instructiuni de tip INSERT.
master1> DESCRIBE sakila.actor; +-------------+-------------------+------+-----+-------------------+-----------------------------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------------+------+-----+-------------------+-----------------------------------------------+ | actor_id | smallint unsigned | NO | PRI | NULL | auto_increment | | first_name | varchar(45) | NO | | NULL | | | last_name | varchar(45) | NO | MUL | NULL | | | last_update | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP | +-------------+-------------------+------+-----+-------------------+-----------------------------------------------+ 4 rows in set (0.00 sec) master1> INSERT INTO sakila.actor -> SET first_name='BRUCE', -> last_name='WILLIS'; Query OK, 1 row affected (0.01 sec) master1> SELECT * -> FROM sakila.actor -> ORDER BY last_update DESC -> LIMIT 1; +----------+------------+-----------+---------------------+ | actor_id | first_name | last_name | last_update | +----------+------------+-----------+---------------------+ | 201 | BRUCE | WILLIS | 2021-04-27 05:08:54 | +----------+------------+-----------+---------------------+ 1 row in set (0.00 sec)
Pentru a verifica daca inregistrarea a fost transmisa si serverelor secundare este suficienta rularea interogarii precedente si pe aceste servere de tip replica.
slave1> SELECT * -> FROM sakila.actor -> ORDER BY last_update DESC -> LIMIT 1; +----------+------------+-----------+---------------------+ | actor_id | first_name | last_name | last_update | +----------+------------+-----------+---------------------+ | 201 | BRUCE | WILLIS | 2021-04-27 05:08:54 | +----------+------------+-----------+---------------------+ 1 row in set (0.00 sec)
Arhitectura cu un singur server de tip master si mai multe servere de tip slave se alege pentru a creste performantele de citire a datelor si pentru a reduce astfel traficul la serverul de tip master. Este utilizata in aplicatii in care datele nu trebuie sa fie in permanenta la ultima versiune (replicarea este asincrona). Fiecare server slave nou adaugat in retea va genera un trafic suplimentar catre master. Configurarea unei astfel de arhitecturi se realizeaza identic cu versiunea cu un singur master si un singur slave, doar ca procedura pentru serverele de tip slave va fi repetata.
Replicare master-slave inlantuita
In arhitectura precedenta, daca sunt adaugate prea multe servere de tip slave, vom avea o diminuare a performantelor. Pentru a prelua o parte din sarcini de la serverul master se introduce un server secundar releu, care va servi fisierele log mai departe catre alte servere de tip slave. Aceasta arhitectura (replicare master-slave inlantuita sau chain replication) va reduce incarcarea pe serverul central.
Pentru aceasta arhitectura, pe serverul secundar releu trebuie sa fie activata inregistrarea binara. In acest fel, va fi realizata scrierea evenimentelor preluate de la serverul master intr-un log binar local. Configrarea serverului releu necesita prezenta urmatoarelor optiuni de configurare la nivelul fisierului my.cnf.
root@relay:/# pico /etc/mysql/my.cnf
[mysqld] server_id = 201 log_bin = /var/lib/mysql/binlogs/relay log_slave_updates
root@relay:/# sudo systemctl restart mysql
Activarea optiunii log_slave_updates permite inlantuirea serverelor intr-un proces de replicare. In acest fel, pot fi realizate arhitecturi de genul urmator: A -> B -> C. Cu optiunile log_bin si log_slave_updates activate (setari implicite), actualizarile primite de la A sunt inregistrate de B in logul sau binar si pot fi transmise mai departe catre C.
Replicare master-master
Replicarea de tip master-master presupune existenta a doua noduri master care pot accepta atat cereri de citire, cat si de scriere a datelor. Replicarea intre nodurile master este una de tip asincron. Aceasta arhitectura este utila in furnizarea unui timp cat mai mare de accesibilitate a serverului.
Prin intermediul arhitecturii master-master exista posibilitatea de a scala cererile de scriere nu numai prin cresterea capacitatii de calcul a unui nod, ci si prin adaugarea unui nod suplimentar. In plus, probabilitatea ca ambele nodurile sa cedeze in acelasi timp este una foarte mica. Daca un nod de la nivelul retelei nu mai este disponibil, cel de-al doilea va prelua cererile.
Daca se utilizeaza aceasta arhitectura de replicarea a datelor, pot aparea probleme la inserarea simultana a inregistrarilor in tabele care prezinta campuri ce detin proprietatea auto_increment; fiecare server va incerca sa introduca o inregistrare cu aceiasi valoare pentru cheia primara. Aceasta problema poate fi rezolvata prin precizarea a doua optiuni de configurare in fisierele globale de configurarea ale celor doua servere: auto_increment_increment, respectiv auto_increment_offset.
root@master1:/# pico /etc/mysql/my.cnf
[mysqld] server_id = 101 log_bin = /var/lib/mysql/binlogs/master1 auto_increment_increment = 2 auto_increment_offset = 1
Valoarea optiunii de configurare auto_increment_increment, precizata la nivelul celor doua fisiere de configurare, trebuie sa fie un intreg cel putin egal cu numarul de servere din retea.
root@master2:/# pico /etc/mysql/my.cnf
[mysqld] server_id = 102 log_bin = /var/lib/mysql/binlogs/master2 auto_increment_increment = 2 auto_increment_offset = 2
In exemplul de mai sus, la nivelul fiecarul server valorile pentru campurile care detin proprietatea auto_increment vor fi incrementate cu 2. Daca pentru primul server valorile posibile sunt 1, 3, 5, pentru cel de-al doilea server vor putea fi utilizata valorile de genul 2, 4, 6.
Replicare circulara
Replicarea circulara (multi-master) este o extensie a arhitecturii master-master, putand fi intalnita si sub titulatura de replicare multi-master. Spre deosebire de arhitectura precedenta, aceasta nu poate fi utilizata pentru a asigura o disponibilitate ridicata (HA, high availability).
Daca un server nu poate citi logul binar toate serverele de la nivelul arhitecturii sunt afectate. Nu se recomanda utilizarea acestei topologii in situatii in care datele sunt obligatoriu sincrone.