Historien om fysisk sletning af 300 millioner poster i MySQL

Introduktion

Hej. Jeg er ningenMe, webudvikler.

Som titlen antyder, er min historie en historie om fysisk sletning af 300 millioner poster i MySQL.

Jeg blev interesseret i dette, så jeg besluttede at lave en huskeseddel (vejledning).

Start — Alert

I batch-processen serveren, som jeg bruger og vedligeholder, er der en regelmæssig proces, der dagligt indsamler data fra den sidste måned fra MySQL.

Normalt afsluttes denne proces omkring 1 time, men denne gang blev den ikke afsluttet i 7 eller 8 timer, og alerten stoppede ikke med at dukke op…

Søgning efter årsagen

Jeg prøvede at genstarte processen, kigge i loggene, men så ikke noget alvorligt.
Forespørgslen blev indekseret korrekt. Men da jeg tænkte over, hvad der gik galt, indså jeg, at databasestørrelsen var ganske stor.

hoge_table | 350'000'000 |

350 millioner poster. Det ser ud til, at indekseringen fungerede korrekt, bare meget langsomt.

Den nødvendige datainsamling for måneden var omkring 12.000.000 poster. Det ser ud til, at select-kommandoen tog meget lang tid, og transaktionen blev ikke gennemført i lang tid.

DB

I bund og grund er det en tabel, der hver dag vokser med omkring 400.000 poster. Databasen skulle kun indsamle data fra den sidste måned, og derfor var tanken, at den skulle kunne håndtere dette datavolumen, men desværre var rotationen ikke blevet aktiveret.

Denne database blev ikke udviklet af mig. Jeg overtog den fra en anden udvikler, så der er en følelse af, at dette er teknisk gæld.

Der kom et tidspunkt, hvor volumen af dagligt indsatte data blev stort og endelig nåede grænsen. Det er antaget, at man skal opdele sådanne store datavolumener, men det blev desværre ikke gjort.

Og så kom jeg ind i billedet.

Retning

Det var mere rationelt at reducere selve databasen og forkorte behandlingstiden i stedet for at ændre selve logikken.

Situationen burde ændre sig markant, hvis jeg slettede 300 millioner poster, så jeg besluttede at gøre det… Åh, jeg troede, at det bestemt ville virke.

Handling 1

Efter at have forberedt en pålidelig sikkerhedskopi, begyndte jeg endelig at sende forespørgsler.

「Sender forespørgslen」

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

「…」

「…」

“Hmm… Ingen svar. Måske tager processen lang tid?” — tænkte jeg, men for en sikkerheds skyld kiggede jeg i grafana og så, at diskbelastningen voksede meget hurtigt.
“Det er risikabelt” — tænkte jeg igen og stoppede straks forespørgslen.

Handling 2

Efter at have analyseret alt, indså jeg, at datamængden var for stor til at slette alt på én gang.

Jeg besluttede at skrive et script, som kunne slette omkring 1.000.000 poster, og startede det.

「implementerer script」

“Nu virker det helt sikkert,” tænkte jeg.

Handling 3

Den anden metode fungerede, men viste sig at være meget arbejdskrævende.
For at gøre alt præcist uden unødvendig stress ville det tage omkring to uger. Men dette scenarie levede stadig ikke op til servicekravene, så jeg måtte fravælge det.

Derfor besluttede jeg at:

Kopiere tabellen og give den et nyt navn.

Fra det forrige skridt indså jeg, at sletning af så store datamængder skaber en tilsvarende stor belastning. Derfor besluttede jeg at oprette en ny tabel fra bunden ved hjælp af insert og flytte de data, jeg planlagde at slette, ind i den.

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

Hvis den nye tabel har samme størrelse som ovenfor, burde databehandlingshastigheden også blive 1/7 hurtigere.

Da jeg havde oprettet tabellen og givet den et nyt navn, begyndte jeg at bruge den som master tabel. Nu, hvis jeg sletter tabellen med 300 millioner poster, skulle alt være i orden.
Jeg fandt ud af, at truncate eller drop skaber mindre belastning end delete, og besluttede at bruge denne metode.

Udførelse

「Sender forespørgslen」

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

「…」
「…」
「øhm...?」

Handling 4

Jeg troede, den tidligere idé ville fungere, men efter at have sendt insert-forespørgslen opstod der mange fejl. MySQL skåner ikke.

Jeg var så træt, at jeg begyndte at tænke, at jeg ikke ville gøre dette mere.

Jeg satte mig ned og tænkte, at måske var der for mange insert-forespørgsler for én gang...
Jeg forsøgte at sende en insert-forespørgsel med en datamængde, som databasen skulle håndtere på en dag. Det lykkedes!

Og så fortsatte vi med at sende forespørgsler med den samme datamængde. Da vi skulle fjerne en måneds datamængde, gentog vi denne operation omkring 35 gange.

Omdøbning af tabellen

Her var heldet på min side: alt gik glat.

Alerts forsvandt.

Hastigheden for batchbehandling blev øget.

Tidligere tog denne proces omkring en time, nu tager det cirka 2 minutter.

Efter at have bekræftet, at alle problemer var løst, droppede jeg 300 millioner poster. Jeg slettede tabellen og følte mig genfødt.

Resumé

Jeg indså, at rotate processing blev overset under batchbehandlingen, og det var det, der udgjorde det primære problem. En sådan fejl i arkitekturen fører til spild af tid.

Tænker du over belastningen ved datareplikering, når du sletter poster fra databasen? Lad os ikke overbelaste MySQL.

De, der har god forståelse for databaser, vil bestemt ikke møde et sådant problem. Og for de andre håber jeg, at denne artikel har været nyttig.

Tak for læsningen!

Vi vil være meget glade, hvis du fortæller os, om du kunne lide denne artikel, om oversættelsen var klar, og om den var nyttig for dig?

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster