Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como reconstruir um escravo MySQL inconsistente?

Os escravos MySQL podem se tornar inconsistentes. Você pode tentar evitá-lo, mas é muito difícil. Definir super_read_only e usar replicação baseada em linha pode ajudar muito, mas não importa o que você faça, ainda é possível que seu escravo fique inconsistente.

O que pode ser feito para reconstruir um escravo MySQL inconsistente? Neste post do blog, vamos dar uma olhada nesse problema.

Primeiro, vamos discutir o que precisa acontecer para reconstruir um escravo. Para trazer um nó para a Replicação MySQL, ele deve ser provisionado com dados de um dos nós na topologia de replicação. Esses dados devem ser consistentes no momento em que foram coletados. Você não pode tomá-lo em uma tabela por tabela ou esquema por esquema, porque isso tornará o nó provisionado inconsistente internamente. Isso significa que alguns dados seriam mais antigos do que alguma outra parte do conjunto de dados.

Além da consistência dos dados, também deve ser possível coletar informações sobre a relação entre os dados e o estado de replicação. Você deseja ter uma posição de log binário na qual os dados coletados sejam consistentes ou um ID de transação global da transação que foi a última executada no nó que é a origem dos dados.

Isso nos leva às seguintes considerações. Você pode reconstruir um escravo usando qualquer ferramenta de backup, desde que essa ferramenta possa gerar backup consistente e inclua coordenadas de replicação para o momento em que o backup é consistente. Isso nos permite escolher entre algumas opções.

Usando o Mysqldump para reconstruir um escravo MySQL inconsistente

Mysqldump é a ferramenta mais básica que temos para conseguir isso. Ele nos permite criar um backup lógico, entre outros, na forma de instruções SQL. O que é importante, apesar de básico, ainda nos permite fazer um backup consistente:ele pode usar transação para garantir que os dados sejam consistentes no início da transação. Ele também pode anotar as coordenadas de replicação para esse ponto, até mesmo uma instrução CHANGE MASTER inteira, facilitando o início da replicação usando o backup.

Usando o Mydumper para reconstruir um escravo MySQL inconsistente

Outra opção é usar mydumper - esta ferramenta, assim como o mysqldump, gera um backup lógico e, assim como o mysqldump, pode ser usado para criar um backup consistente do banco de dados. A principal diferença entre mydumper e mysqldump é que mydumper, quando emparelhado com myloader, pode fazer dump e restaurar dados em paralelo, melhorando o dump e, principalmente, o tempo de restauração.

Usando um instantâneo para reconstruir um escravo MySQL inconsistente

Para quem usa provedores de nuvem, uma possibilidade é tirar um instantâneo do armazenamento em bloco subjacente. Os instantâneos geram uma visualização pontual dos dados. Esse processo é bastante complicado, pois a consistência dos dados e a capacidade de restaurá-los dependem principalmente da configuração do MySQL.

Você deve garantir que o banco de dados funcione em um modo durável (ele está configurado de forma que o travamento do MySQL não resulte em nenhuma perda de dados). Isso ocorre porque (do ponto de vista do MySQL) tirar um instantâneo de volume e, em seguida, iniciar outra instância do MySQL a partir dos dados armazenados nela é, basicamente, o mesmo processo como se você matasse -9 o mysqld e o iniciasse novamente. A recuperação do InnoDB precisa acontecer, reproduzir transações que foram armazenadas em logs binários, reverter transações que não foram concluídas antes da falha e assim por diante.

A desvantagem do processo de reconstrução baseado em instantâneo é que ele está fortemente vinculado ao fornecedor atual. Você não pode copiar facilmente os dados do instantâneo de um provedor de nuvem para outro. Você pode movê-lo entre diferentes regiões, mas ainda será o mesmo provedor.

Usando um Xtrabackup ou Mariabackup para reconstruir um MySQL Slave inconsistente

Finalmente, xtrabackup/mariabackup - esta é uma ferramenta escrita por Percona e bifurcada por MariaDB que permite gerar um backup físico. É muito mais rápido que os backups lógicos - é limitado principalmente pelo desempenho do hardware - disco ou rede sendo os gargalos mais prováveis. A maior parte da carga de trabalho está relacionada à cópia de arquivos do diretório de dados do MySQL para outro local (no mesmo host ou pela rede).

Embora não seja tão rápido quanto os instantâneos de armazenamento em bloco, o xtrabackup é muito mais flexível e pode ser usado em qualquer ambiente. O backup que produz consiste em arquivos, portanto é perfeitamente possível copiar o backup para qualquer local que desejar. Outro provedor de nuvem, seu datacenter local, não importa, desde que você possa transferir arquivos de sua localização atual.

Ele nem precisa ter conectividade de rede - você também pode copiar o backup para algum dispositivo "transferível" como SSD USB ou até pendrive, desde que ele possa conter todos os dados e armazená-los em seu bolso enquanto você se desloca de um datacenter para outro.

Como reconstruir um escravo MySQL usando o Xtrabackup?

Decidimos focar no xtrabackup, dada sua flexibilidade e capacidade de trabalhar na maioria dos ambientes onde o MySQL pode existir. Como você reconstrói seu escravo usando o xtrabackup? Vamos dar uma olhada.

Inicialmente, temos um mestre e um escravo, que sofreram alguns problemas de replicação:

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)

Como você pode ver, há um problema com um dos esquemas. Vamos supor que temos que reconstruir esse nó para trazê-lo de volta à replicação. Aqui estão os passos que temos que realizar.

Primeiro, temos que garantir que o xtrabackup esteja instalado. No nosso caso, usamos o MySQL 8.0, portanto, temos que usar o xtrabackup na versão 8 para garantir a compatibilidade:

[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.

O Xtrabackup é fornecido pelo repositório Percona e o guia para instalá-lo pode ser encontrado aqui:

https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html

A ferramenta deve ser instalada no mestre e no escravo que queremos reconstruir.

Como próximo passo, removeremos todos os dados do escravo “quebrado”:

[email protected]:~# service mysql stop

[email protected]:~# rm -rf /var/lib/mysql/*

A seguir, vamos fazer o backup no mestre e transmiti-lo para o escravo. Lembre-se de que este one-liner específico requer conectividade raiz SSH sem senha do mestre para o escravo:

[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"

No final, você deve ver uma linha importante:

200306 12:10:40 completed OK!

Este é um indicador de que o backup foi concluído corretamente. Algumas coisas ainda podem dar errado, mas pelo menos temos os dados corretos. Em seguida, no escravo, temos que preparar o backup.

[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/

.

.

.

200306 12:16:07 completed OK!

Você deverá ver, novamente, que o processo foi concluído corretamente. Você pode querer agora copiar os dados de volta para o diretório de dados do MySQL. Não precisamos fazer isso, pois armazenamos o backup de streaming diretamente em /var/lib/mysql. O que queremos fazer, porém, é garantir a propriedade correta dos arquivos:

[email protected]:~# chown -R mysql.mysql /var/lib/mysql

Agora, vamos verificar as coordenadas GTID do backup. Nós os usaremos mais tarde ao configurar a replicação.

[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info

binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9

Ok, tudo parece estar bem, vamos iniciar o MySQL e prosseguir com a configuração da replicação:

[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>

Agora temos que definir o gtid_purged para o conjunto GTID que encontramos no backup. Esses são GTID que foram “cobertos” pelo nosso backup. Somente o novo GTID deve ser replicado do mestre.

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)

Como você pode ver, nosso escravo está replicando de seu mestre.

Como reconstruir um escravo MySQL usando ClusterControl?

Se você for um usuário do ClusterControl, ao invés de passar por este processo você pode reconstruir o slave em apenas alguns cliques. Inicialmente, temos um problema claro com a replicação:

Nosso escravo não está replicando corretamente devido a um erro.

Tudo o que precisamos fazer é executar o trabalho “Rebuild Replication Slave” .

Você será apresentado com uma caixa de diálogo onde você deve escolher um nó mestre para o escravo que você deseja reconstruir. Em seguida, clique em Continuar e está tudo pronto. O ClusterControl reconstruirá o escravo e configurará a replicação para você.

Em breve, com base no tamanho do conjunto de dados, você deverá ver o escravo de trabalho:

Como você pode ver, com apenas alguns cliques, o ClusterControl realizou a tarefa de reconstruir o escravo de replicação inconsistente.