Historien om den fysiske sletning af 300 millioner poster i MySQL

Indledning

Hej. Jeg er ningenMe, webudvikler.

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

Jeg blev interesseret i dette, så jeg besluttede at lave en påmindelse (instruktioner).

Hjem - Alert

Batch-serveren, jeg bruger og vedligeholder, har en regelmæssig proces, der indsamler den sidste måneds data fra MySQL én gang om dagen.

Normalt afsluttes denne proces inden for omkring 1 time, men denne gang blev den ikke fuldført i 7 eller 8 timer, og advarslen stoppede ikke med at dukke op...

At finde årsagen

Jeg forsøgte at genstarte processen og se på logfilerne, men jeg så ikke noget galt.
Forespørgslen blev indekseret korrekt. Men da jeg tænkte over, hvad der gik galt, indså jeg, at databasestørrelsen er ret stor.

hoge_table | 350'000'000 |

350 millioner poster. Indeksering så ud til at fungere korrekt, bare meget langsomt.

Den nødvendige dataindsamling pr. måned var cirka 12 poster. Det ser ud til, at select-kommandoen tog lang tid, og transaktionen ikke blev udført i lang tid.

DB

Det er i bund og grund en tabel, der vokser med omkring 400 poster hver dag. Databasen skulle kun indsamle data for den sidste måned, derfor forventedes det, at den ville modstå præcis denne mængde data, men desværre var rotationsoperationen ikke inkluderet.

Denne database er ikke udviklet af mig. Jeg overtog det fra en anden udvikler, så det føltes stadig som teknisk gæld.

Der kom et tidspunkt, hvor mængden af ​​data, der blev indsat dagligt, blev stor og til sidst nåede sin grænse. Det antages, at når man arbejder med en så stor mængde data, vil det være nødvendigt at adskille dem, men det blev desværre ikke gjort.

Og så kom jeg i aktion.

Rettelse

Det var mere rationelt at reducere størrelsen af ​​selve databasen og reducere tiden til at behandle den end at ændre selve logikken.

Situationen skulle ændre sig markant, hvis du sletter 300 millioner poster, så jeg besluttede mig for at gøre det... Øh, jeg tænkte, at det her helt sikkert ville fungere.

Handling 1

Efter at have forberedt en pålidelig backup, begyndte jeg endelig at sende anmodninger.

「Send en anmodning」

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

"..."

"..."

“Hmm... Intet svar. Måske tager processen lang tid?” — Jeg tænkte, men for en sikkerheds skyld kiggede jeg på grafana og så, at diskbelastningen voksede meget hurtigt.
"Farligt," tænkte jeg igen og stoppede straks anmodningen.

Handling 2

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

Jeg besluttede at skrive et script, der kunne slette omkring 1 poster og lancerede det.

「Jeg implementerer scriptet」

"Nu vil det her helt sikkert virke," tænkte jeg.

Handling 3

Den anden metode virkede, men viste sig at være meget arbejdskrævende.
At gøre alt omhyggeligt, uden unødvendige nerver, ville tage omkring to uger. Men stadig opfyldte dette scenarie ikke servicekravene, så vi måtte væk fra det.

Så her er hvad jeg besluttede at gøre:

Kopier tabellen og omdøb den

Fra det forrige trin indså jeg, at sletning af en så stor mængde data skaber en lige så stor belastning. Så jeg besluttede at oprette en ny tabel fra bunden ved hjælp af insert og flytte de data, jeg skulle slette, ind i den.

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

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

Efter at have oprettet tabellen og omdøbt den, begyndte jeg at bruge den som mastertabellen. Hvis jeg nu dropper bordet med 300 millioner poster, burde alt være fint.
Jeg fandt ud af, at trunkering eller slip skaber mindre overhead end sletning og besluttede at bruge denne metode.

udførelse

「Send en anmodning」

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

"..."
"..."
"Em...?"

Handling 4

Jeg troede, at den tidligere idé ville fungere, men efter at have sendt indsættelsesanmodningen, dukkede der flere fejl op. MySQL er ikke tilgivende.

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

Jeg sad og tænkte og indså, at der måske var for mange indsættelsesforespørgsler for én gang...
Jeg forsøgte at sende en indsættelsesanmodning for mængden af ​​data, som databasen skulle behandle på 1 dag. skete!

Nå, efter det fortsætter vi med at sende anmodninger om den samme mængde data. Da vi skal fjerne en måneds data, gentager vi denne handling cirka 35 gange.

Omdøbning af et bord

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

Alarm forsvundet

Batchbehandlingshastigheden er steget.

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

Efter at jeg var sikker på, at alle problemerne var løst, droppede jeg 300 millioner poster. Jeg slettede bordet og følte mig genfødt.

Resumé

Jeg indså, at rotationsbehandling manglede i batchbehandling, og det var hovedproblemet. Denne form for arkitektoniske fejl fører til spild af tid.

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

De, der er velbevandret i databaser, vil bestemt ikke støde på et sådant problem. For resten af ​​jer håber jeg, at denne artikel var nyttig.

Tak fordi du læste med!

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

Kilde: www.habr.com

Tilføj en kommentar