Zgodba o fizičnem brisanju 300 milijonov zapisov v MySQL

Predstavitev

Zdravo. Sem ningenMe, spletni razvijalec.

Kot pove naslov, je moja zgodba zgodba o fizičnem brisanju 300 milijonov zapisov v MySQL.

To me je začelo zanimati, zato sem se odločil narediti opomnik (navodila).

Domov - opozorilo

Paketni strežnik, ki ga uporabljam in vzdržujem, ima reden postopek, ki enkrat na dan zbira podatke zadnjega meseca iz MySQL.

Običajno se ta postopek zaključi v približno 1 uri, toda tokrat ni bil dokončan 7 ali 8 ur in opozorilo se ni nehalo pojavljati ...

Iskanje vzroka

Poskušal sem znova zagnati postopek in pogledati dnevnike, vendar nisem videl nič narobe.
Poizvedba je bila pravilno indeksirana. Toda ko sem pomislil, kaj je narobe, sem ugotovil, da je velikost baze podatkov precej velika.

hoge_table | 350'000'000 |

350 milijonov zapisov. Zdelo se je, da indeksiranje deluje pravilno, le zelo počasno.

Zahtevano zbiranje podatkov na mesec je bilo približno 12 zapisov. Videti je, da je ukaz za izbiro trajal dolgo in transakcija dolgo ni bila izvedena.

DB

V bistvu gre za tabelo, ki se vsak dan poveča za približno 400 vnosov. Baza naj bi zbirala podatke le za zadnji mesec, zato je bilo pričakovati, da bo zdržala ravno tolikšno količino podatkov, žal pa operacija rotacije ni bila vključena.

Te zbirke podatkov nisem razvil jaz. Prevzel sem ga od drugega razvijalca, tako da se je še vedno zdelo kot tehnični dolg.

Prišla je točka, ko je količina dnevno vnesenih podatkov postala velika in končno dosegla svojo mejo. Predvideva se, da bi jih bilo treba pri delu s tako veliko količino podatkov ločiti, vendar to žal ni bilo storjeno.

In potem sem stopil v akcijo.

Popravek

Bolj racionalno je bilo zmanjšati velikost same baze in skrajšati čas za njeno obdelavo, kot pa spremeniti samo logiko.

Situacija bi se morala bistveno spremeniti, če zbrišeš 300 milijonov zapisov, pa sem se tako odločil... Eh, mislil sem, da bo to zagotovo šlo.

Korak 1

Ko sem pripravil zanesljivo varnostno kopijo, sem končno začel pošiljati zahteve.

「Pošiljanje zahteve」

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

"…"

"…"

»Hmm ... Brez odgovora. Morda postopek traja dolgo?« — sem si mislil, a sem za vsak slučaj pogledal grafana in videl, da obremenitev diska zelo hitro narašča.
»Nevarno,« sem spet pomislil in takoj prekinil zahtevo.

Korak 2

Po analizi vsega sem ugotovil, da je količina podatkov prevelika, da bi lahko izbrisal vse naenkrat.

Odločil sem se napisati skripto, ki bi lahko izbrisala okoli 1 zapisov in jo zagnal.

「Implementiram scenarij」

"Zdaj bo to zagotovo delovalo," sem pomislil.

Korak 3

Druga metoda je delovala, vendar se je izkazalo, da je zelo delovno intenzivna.
Da bi vse naredili previdno, brez nepotrebnih živcev, bi trajalo približno dva tedna. Vendar ta scenarij še vedno ni ustrezal zahtevam storitve, zato smo se morali od njega oddaljiti.

Takole sem se odločil narediti:

Kopirajte tabelo in jo preimenujte

Iz prejšnjega koraka sem ugotovil, da brisanje tako velike količine podatkov povzroči enako veliko obremenitev. Zato sem se odločil ustvariti novo tabelo iz nič z uporabo vstavljanja in vanjo premakniti podatke, ki sem jih nameraval izbrisati.

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

Če naredite novo tabelo enake velikosti kot zgoraj, bi morala tudi hitrost obdelave podatkov postati 1/7 hitrejša.

Ko sem ustvaril tabelo in jo preimenoval, sem jo začel uporabljati kot glavno tabelo. Zdaj, če spustim tabelo s 300 milijoni zapisov, bi moralo biti vse v redu.
Ugotovil sem, da obrezovanje ali spuščanje povzroči manj stroškov kot brisanje, in sem se odločil uporabiti to metodo.

Izpolnitev

「Pošiljanje zahteve」

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

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

Korak 4

Mislil sem, da bo prejšnja ideja delovala, vendar se je po pošiljanju zahteve za vstavljanje pojavilo več napak. MySQL ni prizanesljiv.

Bil sem že tako utrujen, da sem začel razmišljati, da tega ne želim več početi.

Sedel sem in razmišljal ter ugotovil, da je bilo morda preveč poizvedb za vstavljanje naenkrat ...
Poskušal sem poslati zahtevo za vstavljanje količine podatkov, ki naj bi jih zbirka podatkov obdelala v 1 dnevu. Zgodilo se je!

No, potem nadaljujemo s pošiljanjem zahtev za isto količino podatkov. Ker moramo odstraniti podatke za en mesec, to operacijo ponovimo približno 35-krat.

Preimenovanje tabele

Tu je bila sreča na moji strani: vse je šlo gladko.

Opozorilo je izginilo

Hitrost paketne obdelave se je povečala.

Prej je ta postopek trajal približno eno uro, zdaj pa približno 2 minuti.

Ko sem bil prepričan, da so vse težave rešene, sem izpustil 300 milijonov zapisov. Izbrisala sem tabelo in se počutila kot prerojena.

Povzetek

Ugotovil sem, da v paketni obdelavi manjka rotacijska obdelava in to je bila glavna težava. Takšna arhitekturna napaka vodi v izgubo časa.

Ali pomislite na obremenitev pri replikaciji podatkov pri brisanju zapisov iz baze? Ne preobremenjujmo MySQL.

Tisti, ki se dobro spoznajo na baze podatkov, zagotovo ne bodo naleteli na takšno težavo. Za ostale upam, da je bil ta članek koristen.

Hvala za branje!

Zelo bomo veseli, če nam poveste, ali vam je bil ta članek všeč, ali je prevod jasen, ali vam je bil koristen?

Vir: www.habr.com

Dodaj komentar