Het verhaal van de fysieke verwijdering van 300 miljoen records in MySQL

Introductie

Hallo. Ik ben ningenMe, webontwikkelaar.

Zoals de titel al zegt, is mijn verhaal het verhaal van het fysiek verwijderen van 300 miljoen records in MySQL.

Ik raakte hierin geïnteresseerd, dus besloot ik een herinnering (instructies) te maken.

Thuis - Waarschuwing

De batchserver die ik gebruik en onderhoud heeft een regelmatig proces dat eenmaal per dag de gegevens van de afgelopen maand uit MySQL verzamelt.

Meestal wordt dit proces binnen ongeveer 1 uur voltooid, maar deze keer duurde het 7 tot 8 uur en bleef de waarschuwing verschijnen...

Het vinden van de reden

Ik heb geprobeerd het proces opnieuw te starten en de logboeken te bekijken, maar ik zag niets verkeerds.
De query is correct geïndexeerd. Maar toen ik nadacht over wat er mis ging, realiseerde ik me dat de databasegrootte behoorlijk groot is.

hoge_table | 350'000'000 |

350 miljoen records. Het indexeren leek correct te werken, alleen erg langzaam.

De benodigde dataverzameling per maand bedroeg circa 12 records. Het lijkt erop dat het selectiecommando lang heeft geduurd en dat de transactie lange tijd niet is uitgevoerd.

DB

Het is in wezen een tabel die elke dag met ongeveer 400 vermeldingen groeit. De database zou alleen gegevens voor de afgelopen maand verzamelen, daarom werd verwacht dat deze precies deze hoeveelheid gegevens zou kunnen verwerken, maar helaas was de rotatiebewerking niet inbegrepen.

Deze database is niet door mij ontwikkeld. Ik nam het over van een andere ontwikkelaar, dus het voelde nog steeds als een technische schuld.

Er kwam een ​​moment waarop de hoeveelheid dagelijks ingevoerde gegevens groot werd en uiteindelijk zijn limiet bereikte. Er wordt aangenomen dat het bij het werken met zo'n grote hoeveelheid gegevens nodig zou zijn om ze te scheiden, maar dit is helaas niet gebeurd.

En toen kwam ik in actie.

Correctie

Het was rationeler om de omvang van de database zelf te verkleinen en de verwerkingstijd ervan te verkorten dan om de logica zelf te veranderen.

De situatie zou aanzienlijk moeten veranderen als je 300 miljoen records wist, dus besloot ik dat te doen... Eh, ik dacht dat dit zeker zou werken.

Actie 1

Nadat ik een betrouwbare back-up had voorbereid, begon ik eindelijk verzoeken te verzenden.

「Een verzoek verzenden」

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

'...'

'...'

“Hm... Geen antwoord. Misschien duurt het proces lang?” — Dacht ik, maar voor het geval dat, ik keek naar grafana en zag dat de schijfbelasting heel snel groeide.
“Gevaarlijk”, dacht ik opnieuw en stopte onmiddellijk het verzoek.

Actie 2

Nadat ik alles had geanalyseerd, realiseerde ik me dat de hoeveelheid gegevens te groot was om alles in één keer te verwijderen.

Ik besloot een script te schrijven dat ongeveer 1 records kon verwijderen en lanceerde het.

「Ik implementeer het script」

“Nu gaat dit zeker lukken”, dacht ik.

Actie 3

De tweede methode werkte, maar bleek erg arbeidsintensief.
Alles zorgvuldig doen, zonder onnodige zenuwen, zou ongeveer twee weken duren. Maar toch voldeed dit scenario niet aan de servicevereisten, dus moesten we ervan afstappen.

Dus dit is wat ik besloot te doen:

Kopieer de tabel en hernoem deze

Uit de vorige stap realiseerde ik me dat het verwijderen van zo'n grote hoeveelheid gegevens een even grote belasting met zich meebrengt. Dus besloot ik een geheel nieuwe tabel te maken met behulp van invoegen en de gegevens die ik wilde verwijderen daarin te verplaatsen.

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

Als u de nieuwe tabel even groot maakt als hierboven, zou de gegevensverwerkingssnelheid ook 1/7 sneller moeten worden.

Nadat ik de tabel had gemaakt en de naam ervan had gewijzigd, begon ik deze als hoofdtabel te gebruiken. Als ik nu de tabel met 300 miljoen records laat vallen, zou alles in orde moeten zijn.
Ik kwam erachter dat afkappen of laten vallen minder overhead veroorzaakt dan verwijderen en besloot deze methode te gebruiken.

executie

「Een verzoek verzenden」

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

'...'
'...'
"Ehm...?"

Actie 4

Ik dacht dat het vorige idee zou werken, maar na het verzenden van het invoegverzoek verschenen er meerdere fouten. MySQL is niet vergevingsgezind.

Ik was al zo moe dat ik begon te denken dat ik dit niet meer wilde doen.

Ik zat te denken en besefte dat er misschien te veel invoegquery's waren voor één keer...
Ik heb geprobeerd een invoegverzoek te sturen voor de hoeveelheid gegevens die de database in 1 dag moet verwerken. Gebeurd!

Welnu, daarna blijven we verzoeken sturen voor dezelfde hoeveelheid gegevens. Omdat we een maand aan gegevens moeten verwijderen, herhalen we deze handeling ongeveer 35 keer.

De naam van een tabel wijzigen

Hier was het geluk aan mijn kant: alles verliep soepel.

Alarm verdwenen

De batchverwerkingssnelheid is toegenomen.

Voorheen duurde dit proces ongeveer een uur, nu duurt het ongeveer 2 minuten.

Nadat ik er zeker van was dat alle problemen waren opgelost, liet ik 300 miljoen records vallen. Ik verwijderde de tabel en voelde me herboren.

Samenvatting

Ik realiseerde me dat rotatieverwerking ontbrak bij batchverwerking, en dat was het grootste probleem. Dit soort architectonische fouten leiden tot tijdverspilling.

Denkt u aan de belasting tijdens gegevensreplicatie bij het verwijderen van records uit de database? Laten we MySQL niet overbelasten.

Degenen die goed thuis zijn in databases zullen een dergelijk probleem zeker niet tegenkomen. Voor de rest van jullie hoop ik dat dit artikel nuttig was.

Bedankt voor het lezen!

We zullen heel blij zijn als je ons vertelt of je dit artikel leuk vond, of de vertaling duidelijk is, of het nuttig voor je was?

Bron: www.habr.com

Voeg een reactie