MariaDB
 sql >> Base de données >  >> RDS >> MariaDB

Comment effectuer une récupération ponctuelle des données MySQL et MariaDB à l'aide de ClusterControl

Les sauvegardes sont cruciales lorsqu'il s'agit de la sécurité des données. Ils constituent la solution ultime de reprise après sinistre :vous n'avez aucun nœud de base de données accessible et votre centre de données pourrait littéralement partir en fumée, mais tant que vous disposez d'une sauvegarde de vos données, vous pouvez toujours vous remettre d'une telle situation.

Généralement, vous utiliserez des sauvegardes pour récupérer à partir de différents types de cas :

  • DROP TABLE ou DELETE accidentels sans clause WHERE, ou avec une clause WHERE qui n'était pas assez spécifique.
  • une mise à jour de la base de données qui échoue et corrompt les données
  • défaillance/corruption du support de stockage

La restauration à partir d'une sauvegarde ne suffit-elle pas ? Qu'est-ce que cela doit être ponctuel? Nous devons garder à l'esprit qu'une sauvegarde est un instantané des données prises à un moment donné. Si vous faites une sauvegarde à 1h00 et qu'une table a été supprimée accidentellement à 11h00, vous pouvez restaurer vos données jusqu'à 1h00 mais qu'en est-il des changements qui se sont produits entre 1h00 et 11h00 ? Ces modifications seraient perdues à moins que vous ne puissiez rejouer les modifications qui se sont produites entre-temps. Heureusement, MySQL dispose d'un tel mécanisme pour stocker les modifications - les journaux binaires. Vous savez peut-être que ces journaux sont utilisés pour la réplication - MySQL les utilise pour stocker toutes les modifications qui se sont produites sur le maître, et un esclave les utilise pour rejouer ces modifications et les appliquer à son ensemble de données. Comme les binlogs stockent toutes les modifications, vous pouvez également les utiliser pour relire le trafic. Dans cet article de blog, nous verrons comment ClusterControl peut vous aider à effectuer une récupération ponctuelle (PITR).

Création d'une sauvegarde compatible avec la récupération ponctuelle

Tout d'abord, parlons des prérequis. Un hôte à partir duquel vous effectuez des sauvegardes doit avoir activé les journaux binaires. Sans eux, PITR n'est pas possible. Deuxième exigence - un hôte à partir duquel vous effectuez des sauvegardes doit disposer de tous les journaux binaires nécessaires pour effectuer une restauration à un moment donné. Si vous utilisez une rotation de journal binaire trop agressive, cela pourrait devenir un problème.

Alors, voyons comment utiliser cette fonctionnalité dans ClusterControl. Tout d'abord, vous devez effectuer une sauvegarde compatible avec PITR. Une telle sauvegarde doit être complète, complète et cohérente. Pour xtrabackup, tant qu'il contient un ensemble de données complet (vous n'avez pas seulement inclus un sous-ensemble de schémas), il sera compatible PITR.

Pour mysqldump, il existe une option pour le rendre compatible PITR. Lorsque vous activez cette option, toutes les options nécessaires seront configurées (par exemple, vous ne pourrez pas choisir de schémas séparés à inclure dans le vidage) et la sauvegarde sera marquée comme disponible pour la récupération à un moment précis.

Récupération ponctuelle à partir d'une sauvegarde

Tout d'abord, vous devez choisir une sauvegarde à restaurer.

Si la sauvegarde est compatible avec PITR, une option sera présentée pour effectuer une récupération ponctuelle. Vous aurez deux options pour cela - "Basé sur le temps" et "Basé sur la position". Discutons de la différence entre ces deux options.

PITR "basé sur le temps"

Avec cette option, vous pouvez passer une date et une heure jusqu'à laquelle la sauvegarde doit être restaurée. Il peut être défini dans une résolution d'une seconde. Il ne garantit pas que toutes les données seront restaurées car, même si vous êtes très précis dans la définition de l'heure, pendant une seconde plusieurs événements pourraient être enregistrés dans le journal binaire. Disons que vous savez que la perte de données s'est produite le 18 avril, à 10:00:01. Vous transmettez la date et l'heure suivantes au formulaire :'2018-04-18 10:00:00'. N'oubliez pas que vous devez utiliser une heure basée sur les paramètres de fuseau horaire du serveur de base de données sur lequel la sauvegarde a été créée.

Il peut toujours arriver que la perte de données ne soit même pas la première qui s'est produite à 10:00:01, de sorte que certains événements seront perdus au cours du processus. Voyons ce que cela signifie.

Pendant une seconde, plusieurs événements peuvent être consignés dans des binlogs. Considérons un tel cas :
10:00:00 - événements A,B,C,D,E,F
10:00:01 - événements V,W,X,Y,Z
où X est l'événement de perte de données. Avec une granularité d'une seconde, vous pouvez soit restaurer jusqu'à tout ce qui s'est passé à 10:00:00 (donc jusqu'à F) soit jusqu'à 10:00:01 (jusqu'à Z). Le dernier cas n'est d'aucune utilité car X serait ré-exécuté. Dans le premier cas, nous manquons V et W.

C'est pourquoi la restauration basée sur la position est plus précise. Vous pouvez dire "Je veux restaurer jusqu'à W".

La restauration basée sur le temps est la plus précise que vous puissiez obtenir sans avoir à accéder aux journaux binaires et à définir la position exacte à laquelle vous souhaitez restaurer. Cela nous amène à la deuxième méthode de faire PITR.

PITR "basé sur la position"

Ici, une certaine expérience des outils de ligne de commande pour MySQL, à savoir l'utilitaire mysqlbinlog, est requise. D'autre part, vous aurez le meilleur contrôle sur la façon dont la récupération sera effectuée.

Passons en revue un exemple simple. Comme vous pouvez le voir dans la capture d'écran ci-dessus, vous devrez transmettre un nom de journal binaire et une position de journal binaire jusqu'à quel point la sauvegarde doit être restaurée. La plupart du temps, il s'agit de la dernière position avant l'événement de perte de données.

Quelqu'un a exécuté une commande SQL qui a entraîné une grave perte de données :

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

Notre application a immédiatement commencé à se plaindre :

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

Nous avons une sauvegarde mais nous voulons restaurer toutes les données jusqu'à ce moment fatal. Tout d'abord, nous supposons que l'application ne fonctionne pas, nous pouvons donc rejeter toutes les écritures qui se sont produites après DROP TABLE comme non importantes. Si votre application fonctionne dans une certaine mesure, vous devrez fusionner les modifications restantes ultérieurement. Ok, examinons les journaux binaires pour trouver la position de l'instruction DROP TABLE. Comme nous voulons éviter d'analyser tous les journaux binaires, trouvons quelle était la position couverte par notre dernière sauvegarde. Vous pouvez vérifier cela en examinant les journaux pour le dernier jeu de sauvegarde et rechercher une ligne similaire à celle-ci :

Donc, nous parlons du nom de fichier 'binlog.000008' et de la position '16184120'. Utilisons cela comme point de départ. Vérifions de quels fichiers journaux binaires nous disposons :

[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

Ainsi, en plus de 'binlog.000008', nous devons également examiner 'binlog.000009'. Exécutons la commande qui convertira les journaux binaires au format SQL à partir de la position que nous avons trouvée dans le journal de sauvegarde :

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

S'il vous plaît, le nœud '--verbose' est requis pour décoder les événements basés sur les lignes. Ce n'est pas nécessairement nécessaire pour le DROP TABLE que nous recherchons, mais pour d'autres types d'événements, cela peut être nécessaire.

Recherchons notre sortie pour la requête 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 */
/*!*/;

Dans cet exemple, nous pouvons voir deux événements. Tout d'abord, à la position 20885489, définit 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'/*!*/;

Deuxièmement, à la position 20885554 se trouve notre événement DROP TABLE. Cela conduit à la conclusion que nous devrions effectuer le PITR jusqu'à la position 20885489. La seule question à laquelle il faut répondre est de quel log binaire nous parlons. Nous pouvons vérifier cela en recherchant les entrées de rotation 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

Comme on peut le voir clairement en comparant les dates, la rotation vers binlog.000009 s'est produite plus tard, nous voulons donc passer binlog.000008 comme fichier binlog dans le formulaire.

Ensuite, nous devons décider si nous allons restaurer la sauvegarde sur le cluster ou voulons-nous utiliser un serveur externe pour la restaurer. Cette deuxième option peut être utile si vous souhaitez restaurer uniquement un sous-ensemble de données. Vous pouvez restaurer une sauvegarde physique complète sur un hôte séparé, puis utiliser mysqldump pour vider les données manquantes et les charger sur le serveur de production.

Gardez à l'esprit que lorsque vous restaurez la sauvegarde sur votre cluster, vous devrez reconstruire des nœuds autres que celui que vous avez récupéré. Dans le scénario maître-esclave, vous souhaiterez généralement restaurer la sauvegarde sur le maître, puis reconstruire les esclaves à partir de celui-ci.

Dans une dernière étape, vous verrez un résumé des actions que ClusterControl prendra.

Enfin, une fois la sauvegarde restaurée, nous testerons si la table manquante a été restaurée ou non :

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

Tout semble ok, nous avons réussi à restaurer les données manquantes.

La dernière étape que nous devons franchir est de reconstruire notre esclave. Veuillez noter qu'il existe une option pour utiliser une sauvegarde PITR. Dans l'exemple ici, ce n'est pas possible car l'esclave répliquerait l'événement DROP TABLE et il finirait par ne pas être cohérent avec le maître.