Подчинените на MySQL могат да станат непоследователни. Можете да се опитате да го избегнете, но наистина е трудно. Задаването на super_read_only и използването на репликация, базирана на редове, може да помогне много, но каквото и да правите, все още е възможно вашият подчинен да стане непоследователен.
Какво може да се направи, за да се изгради отново непоследователен MySQL slave? В тази публикация в блога ще разгледаме този проблем.
Първо, нека обсъдим какво трябва да се случи, за да възстановим роб. За да внесете възел в MySQL репликация, той трябва да бъде снабден с данни от един от възлите в топологията на репликация. Тези данни трябва да са последователни към момента, в който са били събрани. Не можете да го вземете на база таблица по таблица или схема по схема, защото това ще направи предоставения възел несъвместим вътрешно. Това означава, че някои данни биха били по-стари от друга част от набора от данни.
В допълнение към последователността на данните, трябва да е възможно да се събира и информация за връзката между данните и състоянието на репликация. Искате да имате или позиция в двоичен регистър, при която събраните данни са последователни, или глобален идентификатор на транзакция на транзакцията, която е била последната, изпълнена на възела, който е източник на данните.
Това ни води до следните съображения. Можете да възстановите подчинен с помощта на всеки инструмент за архивиране, стига този инструмент да може да генерира последователно архивиране и да включва координати на репликация за момента във времето, в който архивирането е последователно. Това ни позволява да избираме от няколко опции.
Използване на Mysqldump за повторно изграждане на непоследователен MySQL Slave
Mysqldump е най-основният инструмент, с който разполагаме, за да постигнем това. Позволява ни да създадем логическо архивиране, наред с другото, под формата на SQL изрази. Важното е, че макар и основно, той все пак ни позволява да правим последователно архивиране:може да използва транзакцията, за да гарантира, че данните са последователни в началото на транзакцията. Може също така да запише координати на репликация за тази точка, дори и цял оператор CHANGE MASTER, което улеснява стартирането на репликацията с помощта на резервното копие.
Използване на Mydumper за повторно изграждане на непоследователен MySQL Slave
Друга опция е да използвате mydumper – този инструмент, точно като mysqldump, генерира логическо архивиране и, точно като mysqldump, може да се използва за създаване на последователно архивиране на базата данни. Основната разлика между mydumper и mysqldump е, че mydumper, когато е сдвоен с myloader, може да изхвърля и възстановява данни паралелно, подобрявайки изхвърлянето и особено времето за възстановяване.
Използване на моментна снимка за повторно изграждане на непоследователен MySQL Slave
За тези, които използват облачни доставчици, възможността е да направят моментна снимка на основното хранилище на блокове. Моментните снимки генерират изглед на данните в даден момент. Този процес обаче е доста труден, тъй като последователността на данните и възможността за възстановяването им зависят най-вече от конфигурацията на MySQL.
Трябва да се уверите, че базата данни работи в издръжлив режим (тя е конфигурирана по начин, че сривът на MySQL няма да доведе до загуба на данни). Това е така, защото (от гледна точка на MySQL) правенето на моментна снимка на тома и след това стартирането на друг екземпляр на MySQL от съхраняваните в него данни е по същество същият процес, както ако убиете -9 mysqld и след това го стартирате отново. Възстановяването на InnoDB трябва да се случи, да се възпроизведат транзакции, които са били съхранени в двоични регистрационни файлове, транзакции за връщане назад, които не са завършени преди срива и така нататък.
Недостатъкът на процеса на възстановяване, базиран на моментни снимки, е, че той е силно обвързан с текущия доставчик. Не можете лесно да копирате данните за моментни снимки от един доставчик на облак към друг. Може да успеете да го премествате между различни региони, но той пак ще бъде един и същ доставчик.
Използване на Xtrabackup или Mariabackup за възстановяване на непоследователно MySQL Slave
Накрая, xtrabackup/mariabackup - това е инструмент, написан от Percona и разклонен от MariaDB, който позволява да се генерира физическо архивиране. Той е много по-бърз от логическите архиви - ограничен е най-вече от хардуерната производителност - дискът или мрежата са най-вероятните тесни места. По-голямата част от натоварването е свързано с копиране на файлове от MySQL директория с данни на друго място (на същия хост или през мрежата).
Макар че не е толкова бърз, колкото моментните снимки на блоково хранилище, xtrabackup е много по-гъвкав и може да се използва във всяка среда. Архивът, който създава, се състои от файлове, така че е напълно възможно да копирате архива на всяко място, което желаете. Друг доставчик на облак, вашият локален център за данни, няма значение, стига да можете да прехвърляте файлове от текущото си местоположение.
Дори не е нужно да има мрежова свързаност - можете също така просто да копирате архива на някое „прехвърляемо“ устройство като USB SSD или дори USB флаш, стига да може да съдържа всички данни и ги съхранявайте в джоба си, докато се премествате от един център за данни в друг.
Как да възстановим MySQL Slave с помощта на Xtrabackup?
Решихме да се съсредоточим върху xtrabackup, предвид неговата гъвкавост и способност да работи в повечето среди, където MySQL може да съществува. Как да възстановите своя подчинен с помощта на xtrabackup? Нека да разгледаме.
Първоначално имаме главен и подчинен, които страдаха от някои проблеми с репликацията:
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)
Както виждате, има проблем с една от схемите. Да приемем, че трябва да възстановим този възел, за да го върнем обратно в репликацията. Ето стъпките, които трябва да изпълним.
Първо, трябва да се уверим, че xtrabackup е инсталиран. В нашия случай използваме MySQL 8.0, затова трябва да използваме xtrabackup във версия 8, за да гарантираме съвместимост:
[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 се предоставя от хранилището на Percona и ръководството за инсталирането му може да бъде намерено тук:
https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html
Инструментът трябва да бъде инсталиран както на главния, така и на подчинения, който искаме да изградим отново.
Като следваща стъпка ще премахнем всички данни от „счупения“ подчинен:
[email protected]:~# service mysql stop
[email protected]:~# rm -rf /var/lib/mysql/*
След това ще вземем резервното копие на главния и ще го прехвърлим към подчинения. Моля, имайте предвид, че този конкретен едноред изисква SSH root връзка без парола от главния към подчинения:
[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"
В края трябва да видите важен ред:
200306 12:10:40 completed OK!
Това е индикатор, че архивирането е завършено ОК. Няколко неща все още може да се объркат, но поне имаме правилните данни. След това, на подчинения, трябва да подготвим резервното копие.
[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/
.
.
.
200306 12:16:07 completed OK!
Трябва да видите отново, че процесът е завършен ОК. Може да искате сега да копирате данните обратно в директорията с данни на MySQL. Не е нужно да правим това, тъй като съхранихме поточното архивиране директно в /var/lib/mysql. Това, което искаме да направим обаче, е да гарантираме правилното притежание на файловете:
[email protected]:~# chown -R mysql.mysql /var/lib/mysql
Сега нека проверим GTID координатите на резервното копие. Ще ги използваме по-късно при настройката на репликацията.
[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info
binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9
Добре, всичко изглежда е наред, нека стартираме MySQL и да продължим с конфигурирането на репликацията:
[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>
Сега трябва да настроим gtid_purged на набора GTID, който намерихме в архива. Това са GTID, които са „покрити“ от нашето архивиране. Само нов GTID трябва да се репликира от главния.
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)
Както можете да видите, нашият подчинен се копира от своя главен.
Как да възстановим MySQL Slave с помощта на ClusterControl?
Ако сте потребител на ClusterControl, вместо да преминавате през този процес, можете да възстановите подчинения само с няколко щраквания. Първоначално имаме ясен проблем с репликацията:
Нашето подчинено устройство не се репликира правилно поради грешка.
Всичко, което трябва да направим, е да стартираме заданието „Rebuild Replication Slave“ .
Ще ви бъде представен диалогов прозорец, в който трябва да изберете главен възел за робът, който искате да възстановите. След това щракнете върху Напред и сте готови. ClusterControl ще изгради отново подчинения и ще настрои репликацията вместо вас.
Накратко, въз основа на размера на набора от данни, трябва да видите работещ подчинен:
Както можете да видите, само с няколко щраквания ClusterControl изпълни задачата за възстановяване на непоследователния роб на репликация.