MariaDB
 sql >> Base de Dados >  >> RDS >> MariaDB

Como fazer a recuperação pontual de dados MySQL e MariaDB usando o ClusterControl


Os backups são cruciais quando se trata de segurança de dados. Eles são a solução definitiva de recuperação de desastres - você não tem nós de banco de dados alcançáveis ​​e seu datacenter pode literalmente virar fumaça, mas desde que você tenha um backup de seus dados, você ainda pode se recuperar dessa situação.

Normalmente, você usará backups para recuperar de diferentes tipos de casos:
  • DROP TABLE ou DELETE acidental sem uma cláusula WHERE ou com uma cláusula WHERE que não era específica o suficiente.
  • uma atualização de banco de dados que falha e corrompe os dados
  • falha/corrupção na mídia de armazenamento

A restauração do backup não é suficiente? O que tem que ser pontual? Devemos ter em mente que um backup é um instantâneo dos dados obtidos em um determinado momento. Se você fizer um backup à 1h e uma tabela foi removida acidentalmente às 11h, poderá restaurar seus dados até a 1h, mas e as alterações que aconteceram entre 1h e 11h? Essas alterações seriam perdidas, a menos que você pudesse reproduzir as modificações que aconteceram no meio. Felizmente, o MySQL tem um mecanismo para armazenar alterações - logs binários. Você pode saber que esses logs são usados ​​para replicação - o MySQL os usa para armazenar todas as alterações que aconteceram no mestre, e um escravo os usa para reproduzir essas alterações e aplicá-las ao seu conjunto de dados. Como os logs binários armazenam todas as alterações, você também pode usá-los para reproduzir o tráfego. Nesta postagem do blog, veremos como o ClusterControl pode ajudá-lo a realizar a recuperação pontual (PITR).

Criando backup compatível com recuperação pontual


Antes de mais nada, vamos falar sobre os pré-requisitos. Um host de onde você faz backups precisa ter os logs binários ativados. Sem eles, o PITR não é possível. Segundo requisito - um host de onde você faz backups deve ter todos os logs binários necessários para restaurar em um determinado momento. Se você usar rotação de log binário muito agressiva, isso pode se tornar um problema.

Então, vamos ver como usar esse recurso no ClusterControl. Antes de tudo, você deve fazer um backup compatível com o PITR. Esse backup deve ser completo, completo e consistente. Para xtrabackup, desde que contenha um conjunto de dados completo (você não incluiu apenas um subconjunto de esquemas), ele será compatível com PITR.

Para mysqldump, existe uma opção para torná-lo compatível com PITR. Ao habilitar essa opção, todas as opções necessárias serão configuradas (por exemplo, você não poderá escolher esquemas separados para incluir no dump) e o backup será marcado como disponível para recuperação pontual.

Recuperação pontual de um backup


Primeiro, você deve escolher um backup para restaurar.

Caso o backup seja compatível com PITR, será apresentada uma opção para realizar uma Recuperação Point-In-Time. Você terá duas opções para isso - "Baseado no tempo" e "Baseado na posição". Vamos discutir a diferença entre essas duas opções.

PITR "baseado no tempo"


Com esta opção você pode passar uma data e hora, até a qual o backup deve ser restaurado. Pode ser definido dentro de um segundo de resolução. Não garante que todos os dados serão restaurados porque, mesmo que você seja muito preciso na definição do tempo, durante um segundo vários eventos podem ser registrados no log binário. Digamos que você saiba que a perda de dados aconteceu em 18 de abril, às 10:00:01. Você passa a seguinte data e hora para o formulário:‘2018-04-18 10:00:00’. Lembre-se de que você deve usar um horário baseado nas configurações de fuso horário no servidor de banco de dados no qual o backup foi criado.

Ainda pode acontecer que a perda de dados não tenha sido a primeira que aconteceu às 10:00:01, então alguns dos eventos serão perdidos no processo. Vejamos o que isso significa.

Durante um segundo, vários eventos podem ser registrados em logs binários. Vamos considerar esse caso:
10:00:00 - eventos A,B,C,D,E,F
10:00:01 - eventos V,W,X,Y,Z
onde X é o evento de perda de dados. Com uma granularidade de um segundo, você pode restaurar tudo o que aconteceu às 10:00:00 (até F) ou até 10:00:01 (até Z). O último caso é inútil, pois X seria reexecutado. No primeiro caso, perdemos V e W.

É por isso que a restauração baseada em posição é mais precisa. Você pode dizer "Quero restaurar até W".

A restauração baseada em tempo é a mais precisa que você pode obter sem precisar acessar os logs binários e definir a posição exata para onde deseja restaurar. Isso nos leva ao segundo método de fazer PITR.

PITR “Baseado na Posição”


Aqui é necessária alguma experiência com ferramentas de linha de comando para MySQL, como o utilitário mysqlbinlog. Por outro lado, você terá o melhor controle sobre como a recuperação será feita.

Vamos a um exemplo simples. Como você pode ver na captura de tela acima, você terá que passar um nome de log binário e uma posição de log binário até o ponto em que o backup deve ser restaurado. Na maioria das vezes, essa deve ser a última posição antes do evento de perda de dados.

Alguém executou um comando SQL que resultou em uma séria perda de dados:
mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)

Nosso aplicativo imediatamente começou a reclamar:
sysbench 1.1.0-ecf1191 (using bundled LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 2
Report intermediate results every 1 second(s)
Initializing random number generator from current time


Initializing worker threads...

Threads started!

FATAL: mysql_drv_query() returned error 1146 (Table 'sbtest.sbtest1' doesn't exist) for query 'DELETE FROM sbtest1 WHERE id=5038'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:490: SQL error, errno = 1146, state = '42S02': Table 'sbtest.sbtest1' doesn't exist

Temos um backup, mas queremos restaurar todos os dados até aquele momento fatal. Em primeiro lugar, assumimos que o aplicativo não funciona, então podemos descartar todas as gravações que aconteceram após o DROP TABLE como não importantes. Se seu aplicativo funcionar até certo ponto, você terá que mesclar as alterações restantes posteriormente. Ok, vamos examinar os logs binários para encontrar a posição da instrução DROP TABLE. Como queremos evitar analisar todos os logs binários, vamos descobrir qual foi a posição que nosso último backup cobriu. Você pode verificar isso examinando os logs do conjunto de backup mais recente e procurando uma linha semelhante a esta:

Então, estamos falando sobre o nome do arquivo 'binlog.000008' e a posição '16184120'. Vamos usar isso como nosso ponto de partida. Vamos verificar quais arquivos de log binários temos:
[email protected]:~# ls -alh /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql  58M Apr 17 08:31 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql 116M Apr 17 08:59 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql 379M Apr 17 09:30 /var/lib/mysql/binlog.000003
-rw-r----- 1 mysql mysql 344M Apr 17 10:54 /var/lib/mysql/binlog.000004
-rw-r----- 1 mysql mysql 892K Apr 17 10:56 /var/lib/mysql/binlog.000005
-rw-r----- 1 mysql mysql  74M Apr 17 11:03 /var/lib/mysql/binlog.000006
-rw-r----- 1 mysql mysql 5.2M Apr 17 11:06 /var/lib/mysql/binlog.000007
-rw-r----- 1 mysql mysql  21M Apr 18 11:35 /var/lib/mysql/binlog.000008
-rw-r----- 1 mysql mysql  59K Apr 18 11:35 /var/lib/mysql/binlog.000009
-rw-r----- 1 mysql mysql  144 Apr 18 11:35 /var/lib/mysql/binlog.index

Portanto, além de 'binlog.000008', também temos 'binlog.000009' para examinar. Vamos executar o comando que converterá os logs binários para o formato SQL a partir da posição que encontramos no log de backup:
[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out

Por favor, o nó '--verbose' é necessário para decodificar eventos baseados em linha. Isso não é necessariamente necessário para o DROP TABLE que estamos procurando, mas para outros tipos de eventos pode ser necessário.

Vamos pesquisar nossa saída para a consulta DROP TABLE:
[email protected]:~# grep -B 7 -A 1 "DROP TABLE" binlog.out
# at 20885489
#180418 11:24:32 server id 1  end_log_pos 20885554 CRC32 0xb89f2e66     GTID    last_committed=38168    sequence_number=38170    rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
# at 20885554
#180418 11:24:32 server id 1  end_log_pos 20885678 CRC32 0xb38a427b     Query    thread_id=54    exec_time=0    error_code=0
use `sbtest`/*!*/;
SET TIMESTAMP=1524050672/*!*/;
DROP TABLE `sbtest1` /* generated by server */
/*!*/;

Nesta amostra podemos ver dois eventos. Primeiro, na posição de 20885489, define a variável GTID_NEXT.
# at 20885489
#180418 11:24:32 server id 1  end_log_pos 20885554 CRC32 0xb89f2e66     GTID    last_committed=38168    sequence_number=38170    rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;

Segundo, na posição 20885554 está nosso evento DROP TABLE. Isso leva à conclusão de que devemos realizar o PITR até a posição 20885489. A única pergunta a ser respondida é de qual log binário estamos falando. Podemos verificar isso procurando por entradas de rotação de log binário:
[email protected]:~# grep  "Rotate to binlog" binlog.out
#180418 11:35:46 server id 1  end_log_pos 21013114 CRC32 0x2772cc18     Rotate to binlog.000009  pos: 4

Como pode ser visto claramente comparando as datas, a rotação para binlog.000009 aconteceu mais tarde, portanto, queremos passar binlog.000008 como o arquivo binlog no formulário.

Em seguida, temos que decidir se vamos restaurar o backup no cluster ou queremos usar um servidor externo para restaurá-lo. Essa segunda opção pode ser útil se você quiser restaurar apenas um subconjunto de dados. Você pode restaurar o backup físico completo em um host separado e, em seguida, usar o mysqldump para despejar os dados ausentes e carregá-los no servidor de produção.

Lembre-se de que, ao restaurar o backup em seu cluster, você terá que reconstruir nós diferentes daquele que você recuperou. No cenário mestre-escravo, você normalmente desejará restaurar o backup no mestre e reconstruir os escravos a partir dele.

Como última etapa, você verá um resumo das ações que o ClusterControl realizará.

Por fim, após a restauração do backup, testaremos se a tabela ausente foi restaurada ou não:
mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)

Tudo parece bem, conseguimos restaurar os dados ausentes.

O último passo que temos que dar é reconstruir nosso escravo. Observe que há uma opção para usar um backup PITR. No exemplo aqui, isso não é possível, pois o escravo replicaria o evento DROP TABLE e acabaria não sendo consistente com o mestre.