sql >> Base de Datos >  >> RDS >> MariaDB

Cómo hacer una recuperación puntual de datos MySQL y MariaDB usando ClusterControl

Las copias de seguridad son cruciales cuando se trata de la seguridad de los datos. Son la mejor solución de recuperación ante desastres:no tiene nodos de base de datos accesibles y su centro de datos literalmente podría haberse convertido en humo, pero siempre que tenga una copia de seguridad de sus datos, aún puede recuperarse de tal situación.

Por lo general, usará copias de seguridad para recuperarse de diferentes tipos de casos:

  • DROP TABLE o DELETE accidental sin una cláusula WHERE, o con una cláusula WHERE que no era lo suficientemente específica.
  • una actualización de la base de datos que falla y corrompe los datos
  • falla/corrupción de los medios de almacenamiento

¿Restaurar desde una copia de seguridad no es suficiente? ¿Qué tiene que ser puntual? Debemos tener en cuenta que una copia de seguridad es una instantánea de los datos tomados en un momento determinado. Si realiza una copia de seguridad a la 1:00 a. m. y una tabla se eliminó accidentalmente a las 11:00 a. m., puede restaurar sus datos hasta la 1:00 a. m., pero ¿qué pasa con los cambios que ocurrieron entre la 1:00 a. m. y las 11:00 a. m.? Esos cambios se perderían a menos que pueda reproducir las modificaciones que ocurrieron en el medio. Afortunadamente, MySQL tiene un mecanismo de este tipo para almacenar cambios:registros binarios. Es posible que sepa que esos registros se usan para la replicación:MySQL los usa para almacenar todos los cambios que ocurrieron en el maestro, y un esclavo los usa para reproducir esos cambios y aplicarlos a su conjunto de datos. Como los binlogs almacenan todos los cambios, también puede usarlos para reproducir el tráfico. En esta publicación de blog, veremos cómo ClusterControl puede ayudarlo a realizar la recuperación en un punto en el tiempo (PITR).

Creación de una copia de seguridad compatible con la recuperación de un momento dado

En primer lugar, hablemos de los requisitos previos. Un host desde el que realiza copias de seguridad debe tener habilitados los registros binarios. Sin ellos, PITR no es posible. Segundo requisito:un host desde el que realiza copias de seguridad debe tener todos los registros binarios necesarios para restaurar a un momento determinado. Si usa una rotación de registros binarios demasiado agresiva, esto podría convertirse en un problema.

Entonces, veamos cómo usar esta función en ClusterControl. En primer lugar, debe realizar una copia de seguridad que sea compatible con PITR. Dicha copia de seguridad debe ser completa, completa y coherente. Para xtrabackup, siempre que contenga un conjunto de datos completo (no incluyó solo un subconjunto de esquemas), será compatible con PITR.

Para mysqldump, hay una opción para hacerlo compatible con PITR. Cuando habilita esta opción, se configurarán todas las opciones necesarias (por ejemplo, no podrá elegir esquemas separados para incluir en el volcado) y la copia de seguridad se marcará como disponible para la recuperación en un momento dado.

Recuperación de un punto en el tiempo desde una copia de seguridad

Primero, debe elegir una copia de seguridad para restaurar.

Si la copia de seguridad es compatible con PITR, se presentará una opción para realizar una Recuperación de un punto en el tiempo. Tendrá dos opciones para eso:"Basado en el tiempo" y "Basado en la posición". Discutamos la diferencia entre esas dos opciones.

PITR "basado en el tiempo"

Con esta opción puede pasar una fecha y hora, hasta la cual se debe restaurar la copia de seguridad. Se puede definir con una resolución de un segundo. No garantiza que se restaurarán todos los datos porque, incluso si es muy preciso al definir el tiempo, durante un segundo se pueden registrar múltiples eventos en el registro binario. Digamos que sabe que la pérdida de datos ocurrió el 18 de abril a las 10:00:01. Pasas la siguiente fecha y hora al formulario:'2018-04-18 10:00:00'. Tenga en cuenta que debe utilizar una hora basada en la configuración de la zona horaria del servidor de la base de datos en el que se creó la copia de seguridad.

Todavía puede suceder que la pérdida de datos no haya sido la primera que ocurrió a las 10:00:01, por lo que algunos de los eventos se perderán en el proceso. Veamos lo que eso significa.

Durante un segundo, se pueden registrar múltiples eventos en binlogs. Consideremos tal caso:
10:00:00 - eventos A,B,C,D,E,F
10:00:01 - eventos V,W,X,Y,Z
donde X es el evento de pérdida de datos. Con una granularidad de un segundo, puede restaurar todo lo que sucedió a las 10:00:00 (hasta F) o hasta las 10:00:01 (hasta Z). El último caso no sirve de nada ya que X se volvería a ejecutar. En el primer caso, extrañamos a V y W.

Es por eso que la restauración basada en la posición es más precisa. Puedes decir "Quiero restaurar hasta W".

La restauración basada en el tiempo es la más precisa que puede obtener sin tener que ir a los registros binarios y definir la posición exacta en la que desea restaurar. Esto nos lleva al segundo método de hacer PITR.

PITR "basado en la posición"

Aquí se requiere algo de experiencia con herramientas de línea de comandos para MySQL, a saber, la utilidad mysqlbinlog. Por otro lado, tendrá el mejor control sobre cómo se realizará la recuperación.

Veamos un ejemplo simple. Como puede ver en la captura de pantalla anterior, deberá pasar un nombre de registro binario y una posición de registro binario hasta el punto en el que se debe restaurar la copia de seguridad. La mayoría de las veces, esta debería ser la última posición antes del evento de pérdida de datos.

Alguien ejecutó un comando SQL que resultó en una grave pérdida de datos:

mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)

Nuestra aplicación inmediatamente comenzó a quejarse:

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

Tenemos una copia de seguridad pero queremos restaurar todos los datos hasta ese momento fatal. En primer lugar, asumimos que la aplicación no funciona, por lo que podemos descartar todas las escrituras que ocurrieron después de DROP TABLE como no importantes. Si su aplicación funciona hasta cierto punto, tendrá que fusionar los cambios restantes más adelante. Ok, examinemos los registros binarios para encontrar la posición de la instrucción DROP TABLE. Como queremos evitar analizar todos los registros binarios, busquemos cuál fue la posición que cubrió nuestra última copia de seguridad. Puede comprobarlo examinando los registros del último conjunto de copias de seguridad y buscando una línea similar a esta:

Entonces, estamos hablando del nombre de archivo 'binlog.000008' y la posición '16184120'. Usemos esto como nuestro punto de partida. Veamos qué archivos de registro binarios tenemos:

[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

Entonces, además de 'binlog.000008', también tenemos 'binlog.000009' para examinar. Ejecutemos el comando que convertirá los registros binarios en formato SQL a partir de la posición que encontramos en el registro de copia de seguridad:

[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out

Se requiere el nodo '--verbose' para decodificar eventos basados ​​en filas. Esto no es necesariamente necesario para la DROP TABLE que estamos buscando, pero puede ser necesario para otro tipo de eventos.

Busquemos nuestra salida para la 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 */
/*!*/;

En este ejemplo podemos ver dos eventos. Primero, en la posición 20885489, establece la variable 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'/*!*/;

En segundo lugar, en la posición 20885554 se encuentra nuestro evento DROP TABLE. Esto lleva a la conclusión de que debemos realizar el PITR hasta la posición 20885489. La única pregunta que hay que responder es de qué registro binario estamos hablando. Podemos comprobarlo buscando entradas de rotación binlog:

[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 se puede ver claramente al comparar las fechas, la rotación a binlog.000009 ocurrió más tarde, por lo que queremos pasar binlog.000008 como archivo binlog en el formulario.

A continuación, tenemos que decidir si vamos a restaurar la copia de seguridad en el clúster o si queremos usar un servidor externo para restaurarla. Esta segunda opción podría ser útil si desea restaurar solo un subconjunto de datos. Puede restaurar una copia de seguridad física completa en un host separado y luego usar mysqldump para volcar los datos faltantes y cargarlos en el servidor de producción.

Tenga en cuenta que cuando restaure la copia de seguridad en su clúster, tendrá que reconstruir nodos distintos al que recuperó. En el escenario maestro-esclavo, normalmente querrá restaurar la copia de seguridad en el maestro y luego reconstruir los esclavos a partir de él.

Como último paso, verá un resumen de las acciones que realizará ClusterControl.

Finalmente, después de restaurar la copia de seguridad, probaremos si la tabla que falta se ha restaurado o no:

mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)

Todo parece estar bien, logramos restaurar los datos faltantes.

El último paso que tenemos que dar es reconstruir nuestro esclavo. Tenga en cuenta que hay una opción para usar una copia de seguridad de PITR. En el ejemplo aquí, esto no es posible ya que el esclavo replicaría el evento DROP TABLE y terminaría no siendo consistente con el maestro.