Podřízené servery MySQL mohou být nekonzistentní. Můžete se tomu pokusit vyhnout, ale je to opravdu těžké. Nastavení super_read_only a použití replikace založené na řádcích může hodně pomoci, ale bez ohledu na to, co uděláte, je stále možné, že váš slave bude nekonzistentní.
Co lze udělat pro přestavbu nekonzistentního slave MySQL? V tomto příspěvku na blogu se podíváme na tento problém.
Nejprve si proberme, co se musí stát, aby bylo možné znovu postavit otroka. Chcete-li uvést uzel do replikace MySQL, musí mu být poskytnuta data z jednoho z uzlů v topologii replikace. Tyto údaje musí být konzistentní v okamžiku, kdy byly shromážděny. Nemůžete to vzít na základě tabulky po tabulce nebo schématu po schématu, protože to způsobí, že zřízený uzel bude interně nekonzistentní. To znamená, že některá data by byla starší než jiná část datové sady.
Kromě konzistence dat by mělo být také možné shromažďovat informace o vztahu mezi daty a stavem replikace. Chcete mít buď pozici binárního protokolu, na které jsou shromážděná data konzistentní, nebo Global Transaction ID transakce, která byla naposledy provedena na uzlu, který je zdrojem dat.
To nás vede k následujícím úvahám. Podřízenou jednotku můžete znovu sestavit pomocí jakéhokoli zálohovacího nástroje, pokud tento nástroj dokáže generovat konzistentní zálohu a obsahuje souřadnice replikace pro časový bod, ve kterém je záloha konzistentní. To nám umožňuje vybrat si z několika možností.
Použití Mysqldump k přestavbě nekonzistentního MySQL Slave
Mysqldump je nejzákladnější nástroj, který k tomu máme. Umožňuje nám vytvořit logickou zálohu mimo jiné ve formě SQL příkazů. Co je důležité, ačkoli je základní, stále nám umožňuje provádět konzistentní zálohu:může použít transakci k zajištění toho, že data jsou na začátku transakce konzistentní. Může také zapsat replikační souřadnice pro tento bod, dokonce i celý příkaz CHANGE MASTER, což usnadňuje spuštění replikace pomocí zálohy.
Použití Mydumper k přestavbě nekonzistentního MySQL Slave
Další možností je použít mydump - tento nástroj, stejně jako mysqldump, generuje logickou zálohu a stejně jako mysqldump jej lze použít k vytvoření konzistentní zálohy databáze. Hlavní rozdíl mezi mydumpem a mysqldump je v tom, že mydumper, když je spárován s myloaderem, může vypisovat a obnovovat data paralelně, čímž se zlepšuje výpis a zejména doba obnovy.
Použití snímku k opětovnému sestavení nekonzistentního MySQL Slave
Pro ty, kteří využívají poskytovatele cloudu, je možnost pořídit snímek základního blokového úložiště. Snímky generují pohled na data v časovém okamžiku. Tento proces je však poměrně složitý, protože konzistence dat a schopnost je obnovit závisí většinou na konfiguraci MySQL.
Měli byste zajistit, aby databáze fungovala v trvalém režimu (je nakonfigurována tak, aby pád MySQL nevedl ke ztrátě dat). Je to proto, že (z hlediska MySQL) pořízení snímku svazku a následné spuštění další instance MySQL z dat v něm uložených je v podstatě stejný proces, jako kdybyste zabili -9 mysqld a poté jej znovu spustili. Musí proběhnout obnova InnoDB, přehrát transakce, které byly uloženy v binárních protokolech, transakce vrácení, které nebyly dokončeny před havárií a tak dále.
Nevýhodou procesu obnovy založeného na snímku je, že je silně svázán s aktuálním dodavatelem. Nelze snadno kopírovat data snímku od jednoho poskytovatele cloudu k jinému. Možná jej budete moci přesouvat mezi různými oblastmi, ale stále to bude stejný poskytovatel.
Použití Xtrabackup nebo Mariabackup k přestavbě nekonzistentního MySQL Slave
Konečně, xtrabackup/mariabackup – toto je nástroj napsaný Perconou a rozvětvený MariaDB, který umožňuje generovat fyzickou zálohu. Je mnohem rychlejší než logické zálohy – je omezeno především výkonem hardwaru – nejpravděpodobnějšími překážkami jsou disk nebo síť. Většina zátěže souvisí s kopírováním souborů z datového adresáře MySQL do jiného umístění (na stejném hostiteli nebo přes síť).
I když není zdaleka tak rychlý jako snímky blokového úložiště, je xtrabackup mnohem flexibilnější a lze jej použít v jakémkoli prostředí. Záloha, kterou vytváří, se skládá ze souborů, takže je dokonale možné zkopírovat zálohu na libovolné místo, které chcete. Jiný poskytovatel cloudu, vaše místní datové centrum, na tom nezáleží, pokud můžete přenášet soubory ze svého aktuálního umístění.
Nemusí mít ani připojení k síti – můžete také zálohu zkopírovat na nějaké „přenosné“ zařízení, jako je USB SSD nebo dokonce USB klíčenka, pokud může obsahovat všechny data a uložte si je do kapsy, zatímco budete přemisťovat z jednoho datového centra do druhého.
Jak znovu sestavit MySQL Slave pomocí Xtrabackup?
Rozhodli jsme se zaměřit na xtrabackup, vzhledem k jeho flexibilitě a schopnosti pracovat ve většině prostředí, kde může existovat MySQL. Jak znovu sestavíte svého otroka pomocí xtrabackup? Pojďme se na to podívat.
Zpočátku máme master a slave, kteří trpěli některými problémy s replikací:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.141
Master_User: rpl_user
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: binlog.000004
Read_Master_Log_Pos: 386
Relay_Log_File: relay-bin.000008
Relay_Log_Pos: 363
Relay_Master_Log_File: binlog.000004
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1007
Last_Error: Error 'Can't create database 'mytest'; database exists' on query. Default database: 'mytest'. Query: 'create database mytest'
Skip_Counter: 0
Exec_Master_Log_Pos: 195
Relay_Log_Space: 756
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'mytest'; database exists' on query. Default database: 'mytest'. Query: 'create database mytest'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1001
Master_UUID: 53d96192-53f7-11ea-9c3c-080027c5bc64
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 200306 11:47:42
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:9
Executed_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:1-8,
ce7d0c38-53f7-11ea-9f16-080027c5bc64:1-3
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
Jak vidíte, došlo k problému s jedním ze schémat. Předpokládejme, že musíme tento uzel přestavět, abychom jej přivedli zpět do replikace. Zde jsou kroky, které musíme provést.
Nejprve se musíme ujistit, že je nainstalován xtrabackup. V našem případě používáme MySQL 8.0, proto musíme použít xtrabackup ve verzi 8, abychom zajistili kompatibilitu:
[email protected]:~# apt install percona-xtrabackup-80
Reading package lists... Done
Building dependency tree
Reading state information... Done
percona-xtrabackup-80 is already the newest version (8.0.9-1.bionic).
0 upgraded, 0 newly installed, 0 to remove and 143 not upgraded.
Xtrabackup poskytuje úložiště Percona a průvodce jeho instalací naleznete zde:
https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html
Nástroj musí být nainstalován na hlavním i podřízeném zařízení, které chceme přestavět.
Jako další krok odstraníme všechna data z „rozbitého“ otroka:
[email protected]:~# service mysql stop
[email protected]:~# rm -rf /var/lib/mysql/*
Dále vezmeme zálohu na master a streamujeme ji do slave. Mějte prosím na paměti, že tento konkrétní jednořádkový modul vyžaduje připojení root SSH bez hesla od hlavního k podřízenému:
[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"
Na konci byste měli vidět důležitý řádek:
200306 12:10:40 completed OK!
Toto je indikátor, že záloha byla dokončena v pořádku. Pár věcí se může ještě pokazit, ale alespoň máme data správně. Dále na slave musíme připravit zálohu.
[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/
.
.
.
200306 12:16:07 completed OK!
Měli byste znovu vidět, že proces byl dokončen v pořádku. Možná budete chtít nyní zkopírovat data zpět do datového adresáře MySQL. Nemusíme to dělat, protože jsme zálohu streamování uložili přímo do /var/lib/mysql. Co však chceme udělat, je zajistit správné vlastnictví souborů:
[email protected]:~# chown -R mysql.mysql /var/lib/mysql
Nyní se podíváme na souřadnice GTID zálohy. Použijeme je později při nastavování replikace.
[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info
binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9
Ok, vše se zdá být v pořádku, spustíme MySQL a pokračujeme v konfiguraci replikace:
[email protected]:~# service mysql start
[email protected]:~# mysql -ppass
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.18-9 Percona Server (GPL), Release '9', Revision '53e606f'
Copyright (c) 2009-2019 Percona LLC and/or its affiliates
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
Nyní musíme nastavit gtid_purged na sadu GTID, kterou jsme našli v záloze. To jsou GTID, které byly „kryty“ naší zálohou. Pouze nové GTID by se mělo replikovat z hlavního serveru.
mysql> SET GLOBAL gtid_purged='53d96192-53f7-11ea-9c3c-080027c5bc64:1-9';
Query OK, 0 rows affected (0.00 sec)
Now we can start the replication:
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.141', MASTER_USER='rpl_user', MASTER_PASSWORD='yIPpgNE4KE', MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.141
Master_User: rpl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000007
Read_Master_Log_Pos: 380
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 548
Relay_Master_Log_File: binlog.000007
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: 380
Relay_Log_Space: 750
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: 1001
Master_UUID: 53d96192-53f7-11ea-9c3c-080027c5bc64
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:10
Executed_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:1-10
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
Jak vidíte, náš otrok se replikuje ze svého pána.
Jak znovu sestavit MySQL Slave pomocí ClusterControl?
Pokud jste uživatelem ClusterControl, můžete místo toho, abyste prošli tímto procesem, znovu sestavit slave pomocí několika kliknutí. Zpočátku máme jasný problém s replikací:
Náš slave se kvůli chybě správně nereplikuje.
Vše, co musíme udělat, je spustit úlohu „Rebuild Replication Slave“ .
Zobrazí se vám dialogové okno, kde byste měli vybrat hlavní uzel pro otroka, kterého chcete přestavět. Poté klikněte na Pokračovat a vše je připraveno. ClusterControl znovu sestaví slave a nastaví replikaci za vás.
Krátce na to, na základě velikosti datové sady byste měli vidět fungující slave:
Jak můžete vidět, pomocí několika kliknutí ClusterControl dokončil úkol znovu vytvořit nekonzistentní replikační slave.