Η αναπαραγωγή δεν είναι αντίγραφο ασφαλείας. Ή όχι? Δείτε πώς χρησιμοποιήσαμε το lazy replication για ανάκτηση διαγράφοντας κατά λάθος συντομεύσεις.
Η αναπαραγωγή δεν είναι το εργαλείο δημιουργίας αντιγράφων ασφαλείας της βάσης δεδομένων σας (gitlab-ce
Με καθυστερημένη αντιγραφή, ανακτήσαμε δεδομένα σε μόλις 1,5 ώρα. Δείτε πώς ήταν.
Ανάκτηση σε χρόνο με την PostgreSQL
Η PostgreSQL έχει μια ενσωματωμένη λειτουργία που επαναφέρει την κατάσταση μιας βάσης δεδομένων σε ένα συγκεκριμένο χρονικό σημείο. Ονομάζεται
Για να χρησιμοποιήσουμε αυτήν τη δυνατότητα για κρύο αντίγραφο ασφαλείας, κάνουμε τακτικά αντίγραφα ασφαλείας βάσης δεδομένων βάσης και το αποθηκεύουμε σε ένα αρχείο (τα αρχεία του GitLab βρίσκονται στο
Τι είναι η καθυστερημένη αναπαραγωγή;
Καθυστερημένη αναπαραγωγή είναι η εφαρμογή αλλαγών από το WAL με καθυστέρηση. Δηλαδή, η συναλλαγή έγινε την ώρα X
, αλλά θα εμφανιστεί στο αντίγραφο με καθυστέρηση d
σε μια ώρα X + d
.
Υπάρχουν 2 τρόποι για να ρυθμίσετε ένα αντίγραφο φυσικής βάσης δεδομένων στο PostgreSQL: επαναφορά αρχείου και αναπαραγωγή ροής.
Πώς να ρυθμίσετε την καθυστερημένη ανάκτηση αντιγράφων ασφαλείας
recovery.conf
. Ένα παράδειγμα:
standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'
Με αυτές τις ρυθμίσεις, έχουμε διαμορφώσει ένα καθυστερημένο αντίγραφο με επαναφορά αρχείου. Χρησιμοποιείται εδώ restore_command
) από το αρχείο και οι αλλαγές θα εφαρμοστούν μετά από οκτώ ώρες (recovery_min_apply_delay
). Το Replica θα παρακολουθεί για αλλαγές στο χρονοδιάγραμμα στο αρχείο, όπως λόγω αποτυχίας συμπλέγματος (recovery_target_timeline
).
С recovery_min_apply_delay
μπορείτε να ρυθμίσετε την αναπαραγωγή ροής λανθάνοντος χρόνου, αλλά υπάρχουν μερικές παγίδες που σχετίζονται με τις υποδοχές αναπαραγωγής, τα καυτά εφεδρικά σχόλια και ούτω καθεξής. Το αρχείο WAL τα αποφεύγει.
Παράμετρος recovery_min_apply_delay
εμφανίστηκε μόνο στην PostgreSQL 9.3. Σε προηγούμενες εκδόσεις, η καθυστερημένη αναπαραγωγή απαιτεί συνδυασμό pg_xlog_replay_pause(), pg_xlog_replay_resume()
) ή κρατήστε τα τμήματα WAL στο αρχείο για τη διάρκεια της καθυστέρησης.
Πώς το κάνει η PostgreSQL;
Είναι ενδιαφέρον να δούμε πώς η PostgreSQL υλοποιεί το lazy restore. Ας δούμε recoveryApplyDelay(XlogReaderState)
static bool
recoveryApplyDelay(XLogReaderState *record)
{
uint8 xact_info;
TimestampTz xtime;
long secs;
int microsecs;
/* nothing to do if no delay configured */
if (recovery_min_apply_delay <= 0)
return false;
/* no delay is applied on a database not yet consistent */
if (!reachedConsistency)
return false;
/*
* Is it a COMMIT record?
*
* We deliberately choose not to delay aborts since they have no effect on
* MVCC. We already allow replay of records that don't have a timestamp,
* so there is already opportunity for issues caused by early conflicts on
* standbys.
*/
if (XLogRecGetRmid(record) != RM_XACT_ID)
return false;
xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
if (xact_info != XLOG_XACT_COMMIT &&
xact_info != XLOG_XACT_COMMIT_PREPARED)
return false;
if (!getRecordTimestamp(record, &xtime))
return false;
recoveryDelayUntilTime =
TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);
/*
* Exit without arming the latch if it's already past time to apply this
* record
*/
TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
&secs, µsecs);
if (secs <= 0 && microsecs <= 0)
return false;
while (true)
{
// Shortened:
// Use WaitLatch until we reached recoveryDelayUntilTime
// and then
break;
}
return true;
}
Η ουσία είναι ότι η καθυστέρηση βασίζεται στον φυσικό χρόνο που καταγράφεται στη χρονική σήμανση της δέσμευσης συναλλαγής (xtime
). Όπως μπορείτε να δείτε, η καθυστέρηση ισχύει μόνο για δεσμεύσεις και δεν επηρεάζει άλλες εγγραφές - όλες οι αλλαγές εφαρμόζονται απευθείας και η δέσμευση καθυστερεί, επομένως θα δούμε τις αλλαγές μόνο μετά τη ρυθμισμένη καθυστέρηση.
Πώς να χρησιμοποιήσετε το lazy replica για την ανάκτηση δεδομένων
Ας υποθέσουμε ότι έχουμε ένα σύμπλεγμα βάσεων δεδομένων στην παραγωγή και ένα αντίγραφο με καθυστέρηση οκτώ ωρών. Ας δούμε πώς να ανακτήσετε δεδομένα χρησιμοποιώντας ένα παράδειγμα
Όταν συνειδητοποιήσαμε το πρόβλημα, εμείς
SELECT pg_xlog_replay_pause();
Με μια παύση, δεν είχαμε κανέναν κίνδυνο το αντίγραφο να επαναλάβει το αίτημα DELETE
. Χρήσιμο πράγμα αν χρειάζεστε χρόνο για να τα καταλάβετε όλα.
Η ουσία είναι ότι το καθυστερημένο αντίγραφο πρέπει να φτάσει τη στιγμή πριν από το αίτημα DELETE
. Γνωρίζαμε περίπου τη φυσική ώρα της αφαίρεσης. Καταργήσαμε recovery_min_apply_delay
και προστέθηκε recovery_target_time
в recovery.conf
. Έτσι, το αντίγραφο φτάνει στην κατάλληλη στιγμή χωρίς καθυστέρηση:
recovery_target_time = '2018-10-12 09:25:00+00'
Με τις χρονικές σημάνσεις, είναι καλύτερο να μειώσετε το πλεόνασμα για να μην χάσετε. Είναι αλήθεια ότι όσο μεγαλύτερη είναι η μείωση, τόσο περισσότερα δεδομένα χάνουμε. Και πάλι, αν παραλείψουμε το αίτημα DELETE
, όλα θα διαγραφούν ξανά και θα πρέπει να ξεκινήσετε από την αρχή (ή ακόμα και να κάνετε ένα κρύο αντίγραφο ασφαλείας για το PITR).
Επανεκκινήσαμε την καθυστερημένη παρουσία Postgres και τα τμήματα WAL επαναλήφθηκαν μέχρι τον καθορισμένο χρόνο. Μπορείτε να παρακολουθείτε την πρόοδο σε αυτό το στάδιο υποβάλλοντας ερώτημα:
SELECT
-- current location in WAL
pg_last_xlog_replay_location(),
-- current transaction timestamp (state of the replica)
pg_last_xact_replay_timestamp(),
-- current physical time
now(),
-- the amount of time still to be applied until recovery_target_time has been reached
'2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
Εάν η χρονική σήμανση δεν αλλάζει πλέον, η επαναφορά έχει ολοκληρωθεί. Μπορείτε να προσαρμόσετε τη δράση recovery_target_action
Η βάση δεδομένων περιήλθε στην πολιτεία πριν από αυτό το ατυχές αίτημα. Τώρα μπορείτε, για παράδειγμα, να εξάγετε δεδομένα. Εξάγαμε τα δεδομένα απομακρυσμένων ετικετών και όλους τους συνδέσμους σε ζητήματα και αιτήματα συγχώνευσης και τα μεταφέραμε στη βάση δεδομένων παραγωγής. Εάν οι απώλειες είναι μεγάλες, μπορείτε απλά να προωθήσετε το αντίγραφο και να το χρησιμοποιήσετε ως το κύριο. Αλλά τότε όλες οι αλλαγές θα χαθούν μετά τη στιγμή στην οποία ανακάμψαμε.
Είναι προτιμότερο να χρησιμοποιείτε αναγνωριστικά συναλλαγών αντί για χρονικές σημάνσεις. Είναι χρήσιμο να καταγράφονται αυτά τα αναγνωριστικά, για παράδειγμα, για δηλώσεις DDL (όπως π.χ DROP TABLE
), με τη χρήση log_statements = 'ddl'
. Αν είχαμε αναγνωριστικό συναλλαγής θα παίρναμε recovery_target_xid
και έτρεξε τα πάντα στη συναλλαγή πριν από το αίτημα DELETE
.
Η επιστροφή στην εργασία είναι πολύ απλή: καταργήστε όλες τις αλλαγές από recovery.conf
και επανεκκινήστε το postgres. Σύντομα το σύνθημα θα έχει και πάλι οκτάωρη καθυστέρηση και είμαστε έτοιμοι για μελλοντικά προβλήματα.
Οφέλη αποκατάστασης
Με ένα καθυστερημένο αντίγραφο, αντί για ένα κρύο αντίγραφο ασφαλείας, δεν χρειάζεται να ξοδεύετε ώρες για να επαναφέρετε ολόκληρο το στιγμιότυπο από το αρχείο. Για παράδειγμα, χρειαζόμαστε πέντε ώρες για να λάβουμε ολόκληρο το αντίγραφο ασφαλείας των 2 TB βάσης. Και τότε πρέπει ακόμα να εφαρμόσετε ολόκληρο το ημερήσιο WAL για να ανακτήσετε στην επιθυμητή κατάσταση (στη χειρότερη περίπτωση).
Ένα καθυστερημένο αντίγραφο είναι καλύτερο από ένα ψυχρό αντίγραφο με δύο τρόπους:
- Δεν χρειάζεται να λάβετε ολόκληρο το αντίγραφο ασφαλείας της βάσης από το αρχείο.
- Υπάρχει ένα σταθερό παράθυρο οκτώ ωρών τμημάτων WAL που πρέπει να επαναληφθούν.
Επίσης, ελέγχουμε συνεχώς εάν το WAL μπορεί να γίνει PITR και θα παρατηρούσαμε γρήγορα καταστροφή ή άλλα προβλήματα με το αρχείο του WAL παρακολουθώντας το ανεκτέλεστο του καθυστερημένου αντιγράφου.
Σε αυτό το παράδειγμα, μας πήρε 50 λεπτά για να επαναφέρουμε, δηλαδή, η ταχύτητα ήταν 110 GB δεδομένων WAL ανά ώρα (το αρχείο ήταν ακόμα ενεργό
Περίληψη: όπου είναι χρήσιμο ένα καθυστερημένο αντίγραφο (και πού όχι)
Χρησιμοποιήστε την καθυστερημένη αναπαραγωγή ως πρώτη βοήθεια εάν χάσετε κατά λάθος δεδομένα και παρατηρήσετε αυτήν την καταστροφή εντός της ρυθμισμένης καθυστέρησης.
Αλλά να έχετε κατά νου: η αναπαραγωγή δεν είναι αντίγραφο ασφαλείας.
Η δημιουργία αντιγράφων ασφαλείας και η αναπαραγωγή έχουν διαφορετικούς σκοπούς. Ένα κρύο αντίγραφο ασφαλείας θα σας φανεί χρήσιμο εάν το δημιουργήσατε κατά λάθος DELETE
ή DROP TABLE
. Δημιουργούμε ένα αντίγραφο ασφαλείας από την ψυχρή αποθήκευση και επαναφέρουμε την προηγούμενη κατάσταση ενός πίνακα ή μιας ολόκληρης βάσης δεδομένων. Αλλά ταυτόχρονα και το αίτημα DROP TABLE
αναπαράγεται σχεδόν αμέσως σε όλα τα αντίγραφα στο σύμπλεγμα εργασίας, επομένως η κανονική αναπαραγωγή δεν θα αποθηκευτεί εδώ. Η ίδια η αναπαραγωγή διατηρεί τη βάση δεδομένων διαθέσιμη όταν μεμονωμένοι διακομιστές μισθώνονται και διανέμει το φορτίο.
Ακόμη και με καθυστερημένο αντίγραφο, μερικές φορές χρειαζόμαστε πραγματικά ένα κρύο αντίγραφο ασφαλείας σε ασφαλές μέρος, εάν ξαφνικά υπάρξει βλάβη στο κέντρο δεδομένων, κρυφή ζημιά ή άλλα συμβάντα που δεν παρατηρείτε αμέσως. Εδώ από μια αναπαραγωγή δεν έχει νόημα.
Σημείωση. επί
Πηγή: www.habr.com