|

Eine einfache Anleitung zu pt-table-sync

Ein Überblick zu pt-table-sync

Es ist wichtig anzumerken, dass dieses Tool Daten verwaltet und es deshalb eine gute Idee ist, vor seiner Ausführung ein Backup deiner Daten zu machen. Wenn du einen Server, der ein Replication Slave ist, mit der Methode –replicate oder –sync-to-master synchronisierst, werden die Änderungen immer auf dem Replication Master vorgenommen und nie direkt auf dem Replication Slave. Das ist in der Regel der einzig sichere Weg, ein Replikat wieder mit dem Master zu synchronisieren. Veränderungen am Replikat sind normalerweise die ursprüngliche Ursache für Probleme. Allerdings sollten die Veränderungen, die es am Master vornimmt, no-op-Veränderungen sein, die die Daten auf ihre aktuellen Werte setzen und keinerlei Auswirkungen auf das Replikat haben. Außerdem ist es wichtig anzumerken, dass es Fälle gibt, bei denen Unterschiede zwischen dem Master und den Replikaten aus verschiedenen Gründen existieren. Dieses Tool weiß darüber nichts, kann mit solchen Fällen nicht umgehen und würde alle fehlenden/neuen Daten gleich behandeln.

Die Grenzen von pt-table-sync

  • Das Tool überprüft die Struktur der Datenbanken/Tabellen nicht auf Unterschiede, sondern geht davon aus, dass diese identisch sind.
  • Das Tool setzt voraus, dass auf dem Master “binlog_format = STATEMENT” gesetzt ist (was die Standardeinstellung ist). 
  • Es müsste vorher eine pt-table-checksum ausgeführt werden.
  • Mit Master-Master-Setups sollte vorsichtig umgegangen werden, indem man –sync-to-master und –no-check-slave benutzt.

pt-table-sync: eine einfache Fallstudie

An dieser Stelle werden wir die Fehler weiter angehen, die wir in der „Anleitung zu pt-table-checksum“ eingeführt haben.

Ruf dir nochmal ins Gedächtnis, welche Unterschiede wir zwischen dem Master und dem Replikat erzeugt haben. Wir haben einen Datensatz geändert, einen Datensatz gelöscht und einen Datensatz aktualisiert:

slave1 [localhost:24029] {msandbox} ((none)) > select chunk,  lower_boundary, upper_boundary, this_crc, master_crc, this_cnt, master_cnt from percona.checksums where tbl='fail' and( this_crc <> master_crc or this_cnt <> master_cnt)\G
*************************** 1. row ***************************
chunk: 2
lower_boundary: 3
upper_boundary: 4
this_crc: 6c6eee37756ea6e6e9581fe3c11218cf
master_crc: 1c8de6ca86846fd0dbc3ca84de1e9d39
this_cnt: 1
master_cnt: 2
*************************** 2. row ***************************
chunk: 4
lower_boundary: 7
upper_boundary: 8
this_crc: 466afe5823613919b3be7a8058e97afb
master_crc: b9e0bb85309d42c382bc4b458ea9eb7e
this_cnt: 2
master_cnt: 2
*************************** 3. row ***************************
chunk: 6
lower_boundary: 8
upper_boundary: NULL
this_crc: 0
master_crc: 0
this_cnt: 1
master_cnt: 0
3 rows in set (0.000 sec)

Und die gleichen Ergebnisse wie oben, die in SQL aber anders erscheinen:

slave1 [localhost:24029] {msandbox} (sync) > select * from fail;
+----+----------+---------------------+
| id | value | dtm |
+----+----------+---------------------+
| 1 | A15F0C16 | 2021-03-18 11:51:09 |
| 2 | 16C13FA0 | 2021-03-18 11:51:09 |
| 3 | 8DA91A62 | 2021-03-18 11:51:10 | ← Die nächste Zeile wurde gelöscht (id=4)
| 5 | D7358D23 | 2021-03-18 11:51:10 |
| 6 | B3EE718A | 2021-03-18 11:51:11 |
| 7 | changed | 2021-03-18 11:51:12 | ← die aktualisierte Zeile
| 8 | DA5A7FF3 | 2021-03-18 11:51:12 |
| 9 | A44B677A | 2021-03-18 11:53:39 | ← die eingefügte Zeile
+----+----------+---------------------+
8 rows in set (0.000 sec)

Jetzt lass uns mal pt-table-sync ausführen. Wir führen das auf dem Master-Server aus und synchronisieren das Replikat mit dem Master. Wir werden nur die Tabelle mit “fail” synchronisieren.

>> # pt-table-sync --sync-to-master h=127.0.0.1,u=msandbox,p=msandbox,P=24029 --databases=sync --tables=fail --print --function MD5

DELETE FROM `sync`.`fail` WHERE `id`='9' LIMIT 1 /*percona-toolkit src_db:sync src_tbl:fail src_dsn:P=24028,h=127.0.0.1,p=...,u=msandbox dst_db:sync dst_tbl:fail dst_dsn:P=24029,h=127.0.0.1,p=...,u=msandbox lock:1 transaction:1 changing_src:1 replicate:0 bidirectional:0 pid:16888 user:root host:local*/;

REPLACE INTO `sync`.`fail`(`id`, `value`, `dtm`) VALUES ('4', '8009C58E', '2021-03-18 11:51:10') /*percona-toolkit src_db:sync src_tbl:fail src_dsn:P=24028,h=127.0.0.1,p=...,u=msandbox dst_db:sync dst_tbl:fail dst_dsn:P=24029,h=127.0.0.1,p=...,u=msandbox lock:1 transaction:1 changing_src:1 replicate:0 bidirectional:0 pid:16888 user:root host:local*/;

REPLACE INTO `sync`.`fail`(`id`, `value`, `dtm`) VALUES ('7', 'FE0790CF', '2021-03-18 11:51:12') /*percona-toolkit src_db:sync src_tbl:fail src_dsn:P=24028,h=127.0.0.1,p=...,u=msandbox dst_db:sync dst_tbl:fail dst_dsn:P=24029,h=127.0.0.1,p=...,u=msandbox lock:1 transaction:1 changing_src:1 replicate:0 bidirectional:0 pid:16888 user:root host:local*/;

Was wir hier sehen ist, dass das Tool nur die Zeile mit id=9 gelöscht hat, und wir sehen, welche wir ursprünglich hinzugefügt haben.

Die nächste Veränderung ist id=4. Wir haben anfangs eine Zeile gelöscht und das Skript hat hier die Zeile mit id=4 erneut eingefügt.

Die nächste Veränderung ist id=7. Zu Beginn hatten wir den Wert auf “changed” aktualisiert und wir können hier sehen, dass der Original-Wert erneut eingefügt wurde.

Wir benutzen die Option –print und deshalb hat das Skript nichts auf dem Master/Replikat geändert. Es hat nur drei Statements erzeugt, die das Replikat mit dem Master synchronisieren sollen. Jetzt können wir die Veränderungen überprüfen und auf dem problematischen Knoten ausführen. Es ist wichtig anzumerken, dass es möglich ist, dass die angewendeten Veränderungen nicht atomar sind. In diesem Fall solltest du sie atomar machen, indem du:

  • alle drei Statements mit einem “start transaction/commit” einklammerst.
  • die Statements mit “lock table X write/unlock tables” einklammerst.