Η ιστορία της φυσικής διαγραφής 300 εκατομμυρίων εγγραφών στη MySQL

Εισαγωγή

Γειά σου. Είμαι ο ningenMe, προγραμματιστής ιστού.

Όπως λέει ο τίτλος, η ιστορία μου αφορά τη φυσική διαγραφή 300 εκατομμυρίων εγγραφών στη MySQL.

Με ενδιέφερε αυτό, οπότε αποφάσισα να κάνω ένα σημείωμα (οδηγία).

Έναρξη - Ειδοποίηση

Ο διακομιστής παρτίδας που χρησιμοποιώ και διατηρώ έχει μια τακτική διαδικασία που συλλέγει τα δεδομένα του τελευταίου μήνα από τη MySQL μία φορά την ημέρα.

Συνήθως αυτή η διαδικασία ολοκληρώνεται σε περίπου 1 ώρα, αλλά αυτή τη φορά δεν ολοκληρώθηκε για 7 ή 8 ώρες και η ειδοποίηση δεν σταμάτησε να εμφανίζεται...

Βρίσκοντας τον λόγο

Προσπάθησα να επανεκκινήσω τη διαδικασία, να κοιτάξω τα αρχεία καταγραφής, αλλά δεν είδα τίποτα τρομερό.
Το ερώτημα ευρετηριάστηκε σωστά. Όταν όμως σκέφτηκα τι δεν πήγαινε καλά, συνειδητοποίησα ότι ο όγκος της βάσης δεδομένων είναι αρκετά μεγάλος.

hoge_table | 350'000'000 |

350 εκατομμύρια δίσκοι. Η ευρετηρίαση φαινόταν να λειτουργεί σωστά, απλώς πολύ αργά.

Η απαιτούμενη μηνιαία συλλογή δεδομένων ήταν περίπου 12 εγγραφές. Φαίνεται ότι η εντολή Select πήρε πολύ χρόνο και η συναλλαγή δεν έχει εκτελεστεί για μεγάλο χρονικό διάστημα.

DB

Βασικά, είναι ένας πίνακας που αυξάνεται κατά περίπου 400 εγγραφές κάθε μέρα. Η βάση δεδομένων έπρεπε να συλλέγει δεδομένα μόνο για τον τελευταίο μήνα, επομένως, ο υπολογισμός ήταν ότι θα άντεχε ακριβώς αυτόν τον όγκο δεδομένων, αλλά, δυστυχώς, η λειτουργία περιστροφής δεν συμπεριλήφθηκε.

Αυτή η βάση δεδομένων δεν σχεδιάστηκε από εμένα. Το πήρα από άλλο προγραμματιστή, οπότε μου φάνηκε τεχνικό χρέος.

Ήρθε μια στιγμή που ο όγκος των ημερήσιων δεδομένων που εισήχθησαν έγινε μεγάλος και τελικά έφτασε στο όριο. Υποτίθεται ότι όταν εργάζεστε με τόσο μεγάλο όγκο δεδομένων, θα ήταν απαραίτητο να τα χωρίσετε, αλλά αυτό, δυστυχώς, δεν έγινε.

Και μετά έμπλεξα.

Διόρθωση

Ήταν πιο λογικό να μειωθεί η ίδια η βάση δεδομένων και να μειωθεί ο χρόνος για την επεξεργασία της παρά να αλλάξει η ίδια η λογική.

Η κατάσταση θα έπρεπε να αλλάξει σημαντικά αν σβήσουν 300 εκατομμύρια δίσκοι, οπότε αποφάσισα να το κάνω... Ε, σκέφτηκα ότι σίγουρα θα λειτουργούσε.

Δράση 1

Έχοντας ετοιμάσει ένα αξιόπιστο αντίγραφο ασφαλείας, τελικά άρχισα να στέλνω αιτήματα.

「Αποστολή αιτήματος」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

「…」

「…」

«Χμ... Δεν υπάρχει απάντηση. Ίσως η διαδικασία διαρκεί πολύ; - Σκέφτηκα, αλλά σε περίπτωση που κοίταξα το grafana και είδα ότι το φορτίο του δίσκου μεγάλωνε πολύ γρήγορα.
"Επικίνδυνο" - ξανασκέφτηκα και αμέσως σταμάτησα το αίτημα.

Δράση 2

Αφού ανέλυσα τα πάντα, συνειδητοποίησα ότι ο όγκος των δεδομένων ήταν πολύ μεγάλος για να διαγράψω τα πάντα ταυτόχρονα.

Αποφάσισα να γράψω ένα σενάριο που θα μπορούσε να διαγράψει περίπου 1 καταχωρήσεις και το έτρεξα.

「εφαρμογή του σεναρίου」

«Τώρα θα λειτουργήσει σίγουρα», σκέφτηκα.

Δράση 3

Η δεύτερη μέθοδος λειτούργησε, αλλά ήταν πολύ χρονοβόρα.
Για να γίνουν τα πάντα τακτοποιημένα, χωρίς περιττά νεύρα, θα χρειαζόταν περίπου δύο εβδομάδες. Ωστόσο, αυτό το σενάριο δεν πληρούσε τις απαιτήσεις υπηρεσίας, οπότε έπρεπε να απομακρυνθούμε από αυτό.

Επομένως, ορίστε τι αποφάσισα να κάνω:

Αντιγράψτε τον πίνακα και μετονομάστε

Από το προηγούμενο βήμα, συνειδητοποίησα ότι η διαγραφή τόσο μεγάλου όγκου δεδομένων δημιουργεί ένα εξίσου μεγάλο φορτίο. Ως εκ τούτου, αποφάσισα να δημιουργήσω έναν νέο πίνακα από την αρχή χρησιμοποιώντας το insert και να μετακινήσω τα δεδομένα που επρόκειτο να διαγράψω σε αυτόν.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

Εάν κάνετε τον νέο πίνακα με το ίδιο μέγεθος όπως παραπάνω, η ταχύτητα επεξεργασίας δεδομένων θα πρέπει επίσης να είναι 1/7 μεγαλύτερη.

Μετά τη δημιουργία του πίνακα και τη μετονομασία του, άρχισα να τον χρησιμοποιώ ως κύριο (κύριο) πίνακα. Τώρα, αν ρίξω ένα τραπέζι με 300 εκατομμύρια δίσκους, όλα θα πάνε καλά.
Ανακάλυψα ότι η περικοπή ή η απόθεση δημιουργούν λιγότερα έξοδα από τη διαγραφή και αποφάσισα να χρησιμοποιήσω αυτήν τη μέθοδο.

Εκτέλεση

「Αποστολή αιτήματος」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

「…」
「…」
«Εμ…;»

Δράση 4

Νόμιζα ότι η προηγούμενη ιδέα θα λειτουργούσε, αλλά μετά την αποστολή του αιτήματος εισαγωγής, εμφανίστηκε ένα πολλαπλό σφάλμα. Η MySQL δεν έχει έλεος.

Ήμουν ήδη τόσο κουρασμένος που άρχισα να σκέφτομαι ότι δεν θέλω πια να το κάνω αυτό.

Κάθισα και σκέφτηκα και συνειδητοποίησα ότι ίσως υπήρχαν πάρα πολλά αιτήματα εισαγωγής για μία φορά...
Προσπάθησα να στείλω ένα ερώτημα εισαγωγής για τον όγκο των δεδομένων που πρέπει να επεξεργαστεί η βάση δεδομένων σε 1 ημέρα. Συνέβη!

Λοιπόν, μετά από αυτό συνεχίζουμε να στέλνουμε αιτήματα για τον ίδιο όγκο δεδομένων. Εφόσον πρέπει να αφαιρέσουμε τον μηνιαίο όγκο δεδομένων, επαναλαμβάνουμε αυτήν τη λειτουργία περίπου 35 φορές.

Μετονομασία πίνακα

Εδώ η τύχη ήταν με το μέρος μου: όλα πήγαν ομαλά.

Η ειδοποίηση έχει φύγει

Η ταχύτητα επεξεργασίας κατά παρτίδες έχει αυξηθεί.

Προηγουμένως, αυτή η διαδικασία διαρκούσε περίπου μία ώρα, τώρα διαρκεί περίπου 2 λεπτά.

Αφού βεβαιώθηκα ότι όλα τα προβλήματα είχαν λυθεί, έριξα 300 εκατομμύρια δίσκους. Έσβησα τον πίνακα και ένιωσα να ξαναγεννήθηκα.

Περίληψη

Συνειδητοποίησα ότι η επεξεργασία παρτίδας έλειπε από την εναλλαγή επεξεργασίας και αυτό ήταν το κύριο πρόβλημα. Ένα τέτοιο λάθος στην αρχιτεκτονική οδηγεί σε χάσιμο χρόνου.

Σκέφτεστε το φορτίο κατά την αναπαραγωγή δεδομένων διαγράφοντας εγγραφές από τη βάση δεδομένων; Ας μην υπερφορτώνουμε τη MySQL.

Όσοι γνωρίζουν καλά τις βάσεις δεδομένων σίγουρα δεν θα αντιμετωπίσουν τέτοιο πρόβλημα. Για άλλους, ελπίζω ότι αυτό το άρθρο ήταν χρήσιμο.

Ευχαριστώ για την ανάγνωση!

Θα χαρούμε πολύ αν μας πείτε αν σας άρεσε αυτό το άρθρο, είναι κατανοητή η μετάφραση, σας ήταν χρήσιμη;

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο