Uvod
Bok. Ja sam ningenMe, web programer.
Kako stoji u naslovu, moja priča je priča o fizičkom brisanju 300 milijuna zapisa u MySQL-u.
Zanimao sam se za to, pa sam odlučio napraviti bilješku (uputu).
Početak — Alert
U paketu serveru, koji koristim i održavam, postoji redovni proces koji svakodnevno prikuplja podatke za posljednji mjesec iz MySQL-a.
Obično ovaj proces završi otprilike unutar 1 sata, ali ovaj put nije se završavao 7 ili 8 sati, a alert nije prestajao izlaziti…
Istraživanje uzroka
Pokušao sam ponovno pokrenuti proces, pogledati logove, ali nisam vidio ništa ozbiljno.
Upit je bio ispravno indeksiran. No, kada sam razmišljao što ne uspijeva, shvatio sam da je veličina baze podataka prilično velika.
hoge_table | 350'000'000 |350 milijuna zapisa. Čini se da je indeksacija radila ispravno, samo jako sporo.
Zahtevani skup podataka za mjesec iznosio je oko 12 000 000 zapisa. Izgleda da je select naredba potrajala dugo vremena, a transakcija se nije izvršavala.
DB
U suštini, to je tablica koja se svaki dan povećava otprilike za 400 000 zapisa. Baza je trebala prikupljati podatke samo za posljednji mjesec, stoga je procjena bila da će moći podnijeti upravo taj volumen podataka, ali, nažalost, operacija rotacije nije bila uključena.
Ova baza podataka nije bila razvijena od strane mene. Primio sam je od drugog programera, pa je ostao dojam tehničkog duga.
Došao je trenutak kada je volumen podataka koji su se dnevno unosili postao velik i napokon dostigao limit. Pretpostavlja se da bi se s tako velikim volumenom podataka trebali dijeliti, ali to, nažalost, nije napravljeno.
I tu sam ja ušao na scenu.
Ispravak
Bilo je racionalnije smanjiti samu bazu podataka i skratiti vrijeme obrade, nego mijenjati samu logiku.
Situacija bi se trebala značajno promijeniti ako obrišem 300 milijuna zapisa, pa sam odlučio tako i učiniti… Ah, mislio sam da će to zasigurno upaliti.
Akcija 1
Nakon što sam pripremio pouzdanu sigurnosnu kopiju, konačno sam počeo slati upite.
「Slanje upita」
DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';「…」
「…」
“Hmmm… Nema odgovora. Možda proces traje dugo?” — pomislio sam, ali iz predostrožnosti sam pogledao u grafanu i vidio da je opterećenje diska brzo raslo.
"Jako opasno" — pomislio sam još jednom i odmah zaustavio zahtjev.
Akcija 2
Analizirajući sve, shvatio sam da je volumen podataka bio prevelik da bi se sve obrisalo odjednom.
Odlučio sam napisati skriptu koja može obrisati oko 1 000 000 unosa i pokrenuo je.
"realiziram skriptu"
"Sad sigurno radi", — pomislio sam
Akcija 3
Druga metoda je upalila, ali se pokazala vrlo zahtjevnom.
Da sve odradim uredno, bez dodatnog stresa, trebalo bi mi oko dva tjedna. No, ipak, ovaj scenarij nije ispunjavao zahtjeve usluge, pa sam se morao od njega odmaknuti.
Stoga, ovo je što sam odlučio učiniti:
Kopiramo tablicu i preimenujemo je
Iz prethodnog koraka shvatio sam da brisanje tako velikog volumena podataka stvara istu toliku opterećenost. Zato sam odlučio stvoriti novu tablicu od nule pomoću insert i u nju premjestiti podatke koje sam planirao obrisati.
| hoge_table | 350'000'000|
| tmp_hoge_table | 50'000'000|Ako napravim novu tablicu jednake veličine kao što je navedeno iznad, brzina obrade podataka također bi trebala biti 1/7 brža.
Kreiravši tablicu i preimenujući je, počeo sam je koristiti kao glavnu (master) tablicu. Sada, ako obrišem tablicu s 300 milijuna unosa, sve bi trebalo biti u redu.
Saznao sam da truncate ili drop stvaraju manji teret od delete, pa sam odlučio koristiti ovaj način.
Izvršenje
「Slanje upita」
INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS'; 「…」
「…」
"Hm…?"
Akcija 4
Mislim da će prethodna ideja upaliti, ali nakon slanja insert zahtjeva pojavila se višestruka greška. MySQL ne prašta.
Već sam bio toliko umoran da sam počeo razmišljati da više ne želim ovo raditi.
Sjedio sam, razmišljao i shvatio da je možda za jedan put bilo previše insert zahtjeva…
Pokušao sam poslati insert zahtjev za količinu podataka koju baza mora obraditi za 1 dan. Uspeo sam!
Nakon toga nastavljamo slati zahtjeve za istu količinu podataka. Kako trebamo obrisati mjesečnu količinu podataka, ponavljamo ovu operaciju otprilike 35 puta.
Preimenovanje tablice
Ovdje je sreća bila na mojoj strani: sve je prošlo glatko.
Alert su nestali
Brzina obrade serije se povećala.
Ranije je ovaj proces trajao oko sat vremena, sada traje otprilike 2 minute.
Nakon što sam se uvjerio da su svi problemi riješeni, izbrisao sam 300 milijuna zapisa. Obrišao sam tablicu i osjećao se kao da sam se ponovno rodio.
Sažetak
Shvatio sam da je prilikom obrade serija propušteno rotiranje, što je bila glavna problema. Takva greška u arhitekturi dovodi do bespotrebnog trošenja vremena.
Razmišljate li o opterećenju prilikom replikacije podataka, kada brišete zapise iz baze? Ne preopterećujmo MySQL.
Oni koji dobro razumiju baze podataka sigurno se neće susresti s takvim problemom. A ostalima, nadam se, ovaj članak bio od koristi.
Hvala na čitanju!
Bit ćemo vrlo sretni ako nam kažete sviđa li vam se ovaj članak, je li prijevod jasan i je li vam bio koristan?
Izvor: habr.com
