Berättelsen om att fysiskt radera 300 miljoner poster i MySQL

Inledning

Hallå. Jag heter ningenMe, webbutvecklare.

Som titeln säger är min historia historien om att fysiskt radera 300 miljoner poster i MySQL.

Jag blev intresserad av detta, så jag bestämde mig för att göra en påminnelse (instruktioner).

Hem - Alert

Batchservern jag använder och underhåller har en regelbunden process som samlar in den senaste månadens data från MySQL en gång om dagen.

Vanligtvis slutförs denna process inom cirka 1 timme, men den här gången slutfördes den inte på 7 eller 8 timmar, och varningen slutade inte dyka upp...

Att hitta orsaken

Jag försökte starta om processen och titta på loggarna, men jag såg inget fel.
Frågan indexerades korrekt. Men när jag tänkte på vad som gick fel insåg jag att databasstorleken är ganska stor.

hoge_table | 350'000'000 |

350 miljoner poster. Indexering verkade fungera korrekt, bara väldigt långsamt.

Den erforderliga datainsamlingen per månad var cirka 12 000 000 poster. Det ser ut som att select-kommandot tog lång tid och transaktionen inte kördes på länge.

DB

Det är i huvudsak en tabell som växer med cirka 400 000 poster varje dag. Databasen var tänkt att samla in data endast för den senaste månaden, därför förväntades det att den skulle motstå exakt denna mängd data, men tyvärr ingick inte rotationsoperationen.

Denna databas har inte utvecklats av mig. Jag tog över det från en annan utvecklare, så det kändes fortfarande som en teknisk skuld.

Det kom en punkt när mängden data som infogades dagligen blev stor och till slut nådde sin gräns. Det antas att när man arbetar med en så stor mängd data skulle det vara nödvändigt att separera dem, men detta gjordes tyvärr inte.

Och så kom jag till handling.

Korrektion

Det var mer rationellt att minska storleken på själva databasen och minska tiden för bearbetning av den än att ändra själva logiken.

Situationen borde förändras avsevärt om du raderar 300 miljoner poster, så jag bestämde mig för att göra det... Eh, jag trodde definitivt att det här skulle fungera.

Åtgärd 1

Efter att ha förberett en pålitlig säkerhetskopia började jag äntligen skicka förfrågningar.

「Skicka en förfrågan」

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

"..."

"..."

“Hmm... Inget svar. Kanske tar processen lång tid?” — Jag tänkte, men för säkerhets skull tittade jag på grafana och såg att diskbelastningen växte väldigt snabbt.
"Farligt", tänkte jag igen och avbröt direkt begäran.

Åtgärd 2

Efter att ha analyserat allt insåg jag att datamängden var för stor för att radera allt på en gång.

Jag bestämde mig för att skriva ett manus som kunde ta bort cirka 1 000 000 poster och lanserade det.

「Jag implementerar manuset」

"Nu kommer det här definitivt att fungera", tänkte jag.

Åtgärd 3

Den andra metoden fungerade, men visade sig vara mycket arbetskrävande.
Att göra allt noggrant, utan onödiga nerver, skulle ta ungefär två veckor. Men ändå uppfyllde inte detta scenario servicekraven, så vi var tvungna att gå ifrån det.

Så här är vad jag bestämde mig för att göra:

Kopiera tabellen och byt namn på den

Från föregående steg insåg jag att radering av en så stor mängd data skapar en lika stor belastning. Så jag bestämde mig för att skapa en ny tabell från början med hjälp av infoga och flytta data jag skulle ta bort till den.

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

Om du gör den nya tabellen i samma storlek som ovan bör databehandlingshastigheten också bli 1/7 snabbare.

Efter att ha skapat tabellen och döpt om den började jag använda den som huvudtabell. Om jag nu släpper bordet med 300 miljoner poster borde allt vara bra.
Jag fick reda på att trunkering eller släpp skapar mindre overhead än radering och bestämde mig för att använda den här metoden.

utförande

「Skicka en förfrågan」

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

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

Åtgärd 4

Jag trodde att den tidigare idén skulle fungera, men efter att ha skickat insättningsbegäran dök flera fel upp. MySQL är inte förlåtande.

Jag var redan så trött att jag började tänka att jag inte ville göra det här längre.

Jag satt och tänkte och insåg att det kanske var för många infogningsfrågor för en gång...
Jag försökte skicka en insättningsbegäran för mängden data som databasen ska behandla på 1 dag. Hände!

Tja, efter det fortsätter vi att skicka förfrågningar om samma mängd data. Eftersom vi behöver ta bort en månads data, upprepar vi denna operation cirka 35 gånger.

Byter namn på en tabell

Här var turen på min sida: allt gick smidigt.

Alert försvunnet

Batchbearbetningshastigheten har ökat.

Tidigare tog den här processen cirka en timme, nu tar den cirka 2 minuter.

Efter att jag var säker på att alla problem var lösta tappade jag 300 miljoner rekord. Jag tog bort tabellen och kände mig pånyttfödd.

Sammanfattning

Jag insåg att rotationsbearbetning saknades i batchbearbetning, och det var huvudproblemet. Den här typen av arkitektoniska fel leder till slöseri med tid.

Tänker du på belastningen under datareplikering när du tar bort poster från databasen? Låt oss inte överbelasta MySQL.

De som är väl insatta i databaser kommer definitivt inte att stöta på ett sådant problem. För er andra hoppas jag att den här artikeln var användbar.

Tack för att du läser!

Vi blir väldigt glada om du berättar om du gillade den här artikeln, om översättningen är tydlig, om den var användbar för dig?

Källa: will.com

Lägg en kommentar