MariaDB
 sql >> Datenbank >  >> RDS >> MariaDB

Wie man Point-in-Time-Wiederherstellung von MySQL- und MariaDB-Daten mit ClusterControl durchführt

Backups sind entscheidend, wenn es um die Sicherheit von Daten geht. Sie sind die ultimative Notfallwiederherstellungslösung - Sie haben keine erreichbaren Datenbankknoten und Ihr Rechenzentrum hätte buchstäblich in Rauch aufgehen können, aber solange Sie eine Sicherungskopie Ihrer Daten haben, können Sie sich immer noch von einer solchen Situation erholen.

Typischerweise werden Sie Sicherungen verwenden, um sich von verschiedenen Arten von Fällen zu erholen:

  • versehentliches DROP TABLE oder DELETE ohne WHERE-Klausel oder mit einer WHERE-Klausel, die nicht spezifisch genug war.
  • ein Datenbank-Upgrade, das fehlschlägt und die Daten beschädigt
  • Speichermedienfehler/-beschädigung

Reicht die Wiederherstellung aus dem Backup nicht aus? Welcher Zeitpunkt muss es sein? Wir müssen bedenken, dass ein Backup eine Momentaufnahme von Daten ist, die zu einem bestimmten Zeitpunkt erstellt wurden. Wenn Sie um 1:00 Uhr ein Backup erstellen und um 11:00 Uhr versehentlich eine Tabelle entfernt wurde, können Sie Ihre Daten bis 1:00 Uhr wiederherstellen, aber was ist mit Änderungen, die zwischen 1:00 Uhr und 11:00 Uhr aufgetreten sind? Diese Änderungen gehen verloren, es sei denn, Sie können zwischenzeitliche Änderungen wiedergeben. Glücklicherweise hat MySQL einen solchen Mechanismus zum Speichern von Änderungen - Binärlogs. Sie wissen vielleicht, dass diese Protokolle für die Replikation verwendet werden – MySQL verwendet sie, um alle Änderungen zu speichern, die auf dem Master aufgetreten sind, und ein Slave verwendet sie, um diese Änderungen wiederzugeben und sie auf seinen Datensatz anzuwenden. Da die Binlogs alle Änderungen speichern, können Sie sie auch verwenden, um den Datenverkehr wiederzugeben. In diesem Blogbeitrag werfen wir einen Blick darauf, wie ClusterControl Ihnen bei der Point-In-Time-Recovery (PITR) helfen kann.

Erstellen einer Sicherung, die mit der Point-in-Time-Wiederherstellung kompatibel ist

Lassen Sie uns zunächst über die Voraussetzungen sprechen. Auf einem Host, von dem Sie Backups erstellen, müssen Binärprotokolle aktiviert sein. Ohne sie ist PITR nicht möglich. Zweite Anforderung:Ein Host, von dem Sie Backups erstellen, sollte über alle Binärprotokolle verfügen, die für die Wiederherstellung zu einem bestimmten Zeitpunkt erforderlich sind. Wenn Sie eine zu aggressive Binärlog-Rotation verwenden, könnte dies zu einem Problem werden.

Lassen Sie uns also sehen, wie Sie diese Funktion in ClusterControl verwenden. Zunächst müssen Sie ein Backup erstellen, das mit PITR kompatibel ist. Eine solche Sicherung muss vollständig, vollständig und konsistent sein. Für xtrabackup ist es PITR-kompatibel, solange es den vollständigen Datensatz enthält (Sie haben nicht nur eine Teilmenge von Schemas eingeschlossen).

Für mysqldump gibt es eine Option, um es PITR-kompatibel zu machen. Wenn Sie diese Option aktivieren, werden alle erforderlichen Optionen konfiguriert (z. B. können Sie keine separaten Schemas auswählen, die in den Dump aufgenommen werden sollen) und die Sicherung wird als für die Wiederherstellung zu einem bestimmten Zeitpunkt verfügbar markiert.

Point-in-Time-Wiederherstellung aus einer Sicherung

Zuerst müssen Sie ein Backup zum Wiederherstellen auswählen.

Wenn die Sicherung mit PITR kompatibel ist, wird eine Option zur Durchführung einer Point-In-Time-Wiederherstellung angezeigt. Sie haben dafür zwei Optionen – „Zeitbasiert“ und „Positionsbasiert“. Lassen Sie uns den Unterschied zwischen diesen beiden Optionen besprechen.

"Zeitbasiertes" PITR

Mit dieser Option können Sie ein Datum und eine Uhrzeit übergeben, bis zu der das Backup wiederhergestellt werden soll. Es kann mit einer Auflösung von einer Sekunde definiert werden. Es garantiert nicht, dass alle Daten wiederhergestellt werden, da selbst bei sehr genauer Zeitangabe während einer Sekunde mehrere Ereignisse im Binärlog aufgezeichnet werden können. Angenommen, Sie wissen, dass der Datenverlust am 18. April um 10:00:01 Uhr aufgetreten ist. Sie übergeben folgendes Datum und Uhrzeit an das Formular:„2018-04-18 10:00:00“. Bitte denken Sie daran, dass Sie eine Zeit verwenden sollten, die auf den Zeitzoneneinstellungen auf dem Datenbankserver basiert, auf dem die Sicherung erstellt wurde.

Es kann immer noch vorkommen, dass der Datenverlust nicht einmal der erste war, der um 10:00:01 aufgetreten ist, sodass einige der Ereignisse dabei verloren gehen. Sehen wir uns an, was das bedeutet.

Während einer Sekunde können mehrere Ereignisse in Binlogs protokolliert werden. Betrachten wir einen solchen Fall:
10:00:00 - Ereignisse A,B,C,D,E,F
10:00:01 - Ereignisse V,W,X,Y,Z
wobei X das Datenverlustereignis ist. Mit einer Granularität von einer Sekunde können Sie entweder alles wiederherstellen, was um 10:00:00 (also bis F) oder bis 10:00:01 (bis Z) passiert ist. Der letztere Fall ist nutzlos, da X erneut ausgeführt würde. Im ersten Fall vermissen wir V und W.

Aus diesem Grund ist die positionsbasierte Wiederherstellung genauer. Sie können "Ich möchte bis zu W wiederherstellen" sagen.

Die zeitbasierte Wiederherstellung ist die genaueste, die Sie erhalten können, ohne zu den Binärprotokollen gehen und die genaue Position definieren zu müssen, an der Sie wiederherstellen möchten. Dies führt uns zur zweiten Methode, PITR zu machen.

"Positionsbasiertes" PITR

Hier ist etwas Erfahrung mit Befehlszeilentools für MySQL, nämlich dem Dienstprogramm mysqlbinlog, erforderlich. Andererseits haben Sie die beste Kontrolle darüber, wie die Wiederherstellung durchgeführt wird.

Gehen wir ein einfaches Beispiel durch. Wie Sie im obigen Screenshot sehen können, müssen Sie einen Binärlog-Namen und eine Binärlog-Position übergeben, bis zu welcher Stelle die Sicherung wiederhergestellt werden soll. Meistens sollte dies die letzte Position vor dem Datenverlustereignis sein.

Jemand hat einen SQL-Befehl ausgeführt, der zu einem schwerwiegenden Datenverlust geführt hat:

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

Unsere Anwendung fing sofort an zu meckern:

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

Wir haben ein Backup, aber wir wollen alle Daten bis zu diesem fatalen Moment wiederherstellen. Zunächst einmal nehmen wir an, dass die Anwendung nicht funktioniert, sodass wir alle Schreibvorgänge, die nach der DROP TABLE erfolgten, als unwichtig verwerfen können. Wenn Ihre Anwendung einigermaßen funktioniert, müssen Sie die verbleibenden Änderungen später zusammenführen. Ok, untersuchen wir die Binärlogs, um die Position der DROP TABLE-Anweisung zu finden. Da wir vermeiden möchten, alle Binärprotokolle zu analysieren, lassen Sie uns herausfinden, welche Position unser letztes Backup abgedeckt hat. Sie können dies überprüfen, indem Sie die Protokolle auf den neuesten Sicherungssatz untersuchen und nach einer ähnlichen Zeile wie dieser suchen:

Wir sprechen also über den Dateinamen „binlog.000008“ und die Position „16184120“. Lassen Sie uns dies als Ausgangspunkt verwenden. Lassen Sie uns überprüfen, welche binären Protokolldateien wir haben:

[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

Zusätzlich zu „binlog.000008“ müssen wir also auch „binlog.000009“ untersuchen. Lassen Sie uns den Befehl ausführen, der Binärprotokolle in das SQL-Format konvertiert, beginnend mit der Position, die wir im Sicherungsprotokoll gefunden haben:

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

Bitte Knoten ‚--verbose‘ ist erforderlich, um zeilenbasierte Ereignisse zu decodieren. Dies ist nicht unbedingt erforderlich für die DROP TABLE, nach der wir suchen, aber für andere Arten von Ereignissen kann es erforderlich sein.

Lassen Sie uns unsere Ausgabe nach der DROP TABLE-Abfrage durchsuchen:

[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 */
/*!*/;

In diesem Beispiel sehen wir zwei Ereignisse. Zuerst wird an der Position 20885489 die Variable GTID_NEXT gesetzt.

# 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'/*!*/;

Zweitens befindet sich an der Position 20885554 unser DROP TABLE-Ereignis. Dies führt zu dem Schluss, dass wir den PITR bis zur Position 20885489 durchführen sollten. Die einzige zu beantwortende Frage ist, von welchem ​​Binärlog wir sprechen. Wir können das überprüfen, indem wir nach Binlog-Rotationseinträgen suchen:

[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

Wie durch den Vergleich der Daten deutlich zu sehen ist, erfolgte die Rotation zu binlog.000009 später, daher möchten wir binlog.000008 als binlog-Datei im Formular übergeben.

Als nächstes müssen wir entscheiden, ob wir das Backup auf dem Cluster wiederherstellen oder einen externen Server verwenden möchten, um es wiederherzustellen. Diese zweite Option kann nützlich sein, wenn Sie nur einen Teil der Daten wiederherstellen möchten. Sie können eine vollständige physische Sicherung auf einem separaten Host wiederherstellen und dann mysqldump verwenden, um die fehlenden Daten zu sichern und auf den Produktionsserver zu laden.

Denken Sie daran, dass Sie beim Wiederherstellen der Sicherung auf Ihrem Cluster andere Knoten als den, den Sie wiederhergestellt haben, neu erstellen müssen. Im Master-Slave-Szenario möchten Sie normalerweise eine Sicherung auf dem Master wiederherstellen und dann die Slaves daraus neu erstellen.

Als letzten Schritt sehen Sie eine Zusammenfassung der Aktionen, die ClusterControl durchführen wird.

Nachdem die Sicherung wiederhergestellt wurde, testen wir schließlich, ob die fehlende Tabelle wiederhergestellt wurde oder nicht:

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

Alles scheint in Ordnung zu sein, wir konnten fehlende Daten wiederherstellen.

Der letzte Schritt, den wir tun müssen, ist, unseren Sklaven wieder aufzubauen. Bitte beachten Sie, dass es eine Option gibt, ein PITR-Backup zu verwenden. Im Beispiel hier ist dies nicht möglich, da der Slave das DROP TABLE-Ereignis replizieren würde und es am Ende nicht mit dem Master übereinstimmen würde.