Historien om fysisk sletting av 300 millioner poster i MySQL

Innledning

Hallo. Jeg er ningenMe, webutvikler.

Som tittelen sier, er historien min historien om fysisk sletting av 300 millioner poster i MySQL.

Jeg ble interessert i dette, så jeg bestemte meg for å lage en påminnelse (instruksjoner).

Hjem - Alert

Batchserveren jeg bruker og vedlikeholder har en vanlig prosess som samler inn siste måneds data fra MySQL en gang daglig.

Vanligvis fullføres denne prosessen i løpet av omtrent 1 time, men denne gangen ble den ikke fullført på 7 eller 8 timer, og varselet sluttet ikke å dukke opp...

Leter etter en grunn

Jeg prøvde å starte prosessen på nytt og se på loggene, men jeg så ikke noe galt.
Spørringen ble indeksert riktig. Men da jeg tenkte på hva som gikk galt, skjønte jeg at databasestørrelsen er ganske stor.

hoge_table | 350'000'000 |

350 millioner poster. Indeksering så ut til å fungere riktig, bare veldig sakte.

Den nødvendige datainnsamlingen per måned var omtrent 12 000 000 poster. Det ser ut til at select-kommandoen tok lang tid og transaksjonen ikke ble utført på lenge.

DB

Det er egentlig en tabell som vokser med rundt 400 000 oppføringer hver dag. Databasen skulle bare samle inn data for den siste måneden, derfor var det forventet at den ville tåle akkurat denne mengden data, men dessverre ble ikke roteringsoperasjonen inkludert.

Denne databasen er ikke utviklet av meg. Jeg overtok det fra en annen utvikler, så det føltes fortsatt som teknisk gjeld.

Det kom et punkt da volumet av data som ble satt inn daglig ble stort og til slutt nådde sin grense. Det antas at når man arbeider med en så stor mengde data, vil det være nødvendig å skille dem, men dette ble dessverre ikke gjort.

Og så kom jeg i aksjon.

Korreksjon

Det var mer rasjonelt å redusere størrelsen på selve databasen og redusere tiden for behandling av den enn å endre selve logikken.

Situasjonen skulle endre seg betydelig hvis du sletter 300 millioner poster, så jeg bestemte meg for å gjøre det... Eh, jeg trodde dette definitivt ville fungere.

Handling 1

Etter å ha forberedt en pålitelig sikkerhetskopi, begynte jeg endelig å sende forespørsler.

「Sender en forespørsel」

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

"..."

"..."

«Hmm... Ikke noe svar. Kanskje prosessen tar lang tid?» — Jeg tenkte, men for sikkerhets skyld så jeg på grafana og så at diskbelastningen vokste veldig raskt.
"Farlig," tenkte jeg igjen og stoppet umiddelbart forespørselen.

Handling 2

Etter å ha analysert alt, innså jeg at datavolumet var for stort til å slette alt på en gang.

Jeg bestemte meg for å skrive et skript som kunne slette rundt 1 000 000 poster og lanserte det.

「Jeg implementerer manuset」

"Nå vil dette definitivt fungere," tenkte jeg.

Handling 3

Den andre metoden fungerte, men viste seg å være svært arbeidskrevende.
Å gjøre alt nøye, uten unødvendige nerver, ville ta omtrent to uker. Men likevel oppfylte ikke dette scenariet tjenestekravene, så vi måtte gå bort fra det.

Så her er hva jeg bestemte meg for å gjøre:

Kopier tabellen og gi den nytt navn

Fra forrige trinn innså jeg at sletting av en så stor mengde data skaper en like stor belastning. Så jeg bestemte meg for å lage en ny tabell fra bunnen av ved å bruke insert og flytte dataene jeg skulle slette inn i den.

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

Hvis du lager den nye tabellen i samme størrelse som ovenfor, bør databehandlingshastigheten også bli 1/7 raskere.

Etter å ha opprettet tabellen og endret navn på den, begynte jeg å bruke den som hovedtabell. Hvis jeg nå slipper bordet med 300 millioner poster, burde alt være bra.
Jeg fant ut at trunkering eller slipp skaper mindre overhead enn sletting og bestemte meg for å bruke denne metoden.

utførelse

「Sender en forespørsel」

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

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

Handling 4

Jeg trodde den forrige ideen ville fungere, men etter å ha sendt innsettingsforespørselen, dukket det opp flere feil. MySQL er ikke tilgivende.

Jeg var allerede så sliten at jeg begynte å tenke at jeg ikke ville gjøre dette lenger.

Jeg satt og tenkte og skjønte at det kanskje var for mange innsettingsspørsmål for én gang...
Jeg prøvde å sende en innsettingsforespørsel for mengden data som databasen skal behandle i løpet av 1 dag. Skjedde!

Vel, etter det fortsetter vi å sende forespørsler om samme mengde data. Siden vi må fjerne en måneds data, gjentar vi denne operasjonen omtrent 35 ganger.

Gi nytt navn til en tabell

Her var lykken på min side: alt gikk på skinner.

Alarm forsvunnet

Batchbehandlingshastigheten har økt.

Tidligere tok denne prosessen omtrent en time, nå tar den omtrent 2 minutter.

Etter at jeg var sikker på at alle problemene var løst, droppet jeg 300 millioner poster. Jeg slettet tabellen og følte meg gjenfødt.

Sammendrag

Jeg innså at rotasjonsbehandling manglet i batchbehandling, og det var hovedproblemet. Denne typen arkitektoniske feil fører til bortkastet tid.

Tenker du på belastningen under datareplikering når du sletter poster fra databasen? La oss ikke overbelaste MySQL.

De som er godt kjent med databaser vil definitivt ikke støte på et slikt problem. For resten av dere håper jeg denne artikkelen var nyttig.

Takk for at du leste!

Vi vil være veldig glade hvis du forteller oss om du likte denne artikkelen, om oversettelsen er klar, om den var nyttig for deg?

Kilde: www.habr.com

Legg til en kommentar