Zgodba o fizičnem brisanju 300 milijonov zapisov v MySQL

Uvod

Živjo. Sem ningenMe, spletni razvijalec.

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

Zanimalo me je to, zato sem se odločil narediti opomnik (navodila).

Začetek — Alert

V paketnem strežnikom, ki ga uporabljam in vzdržujem, je redni postopek, ki enkrat na dan zbira podatke za pretekli mesec iz MySQL.

Običajno se ta postopek zaključi v približno 1 uri, ampak tokrat se ni zaključil 7 ali 8 ur, in opomnik ni prenehal pojavljati…

Iskanje vzroka

Poskušal sem ponovno zagnati postopek, pogledati dnevnike, toda nič resnega nisem opazil.
Zahteva se je pravilno indeksirala. Toda ko sem razmišljal, kaj gre narobe, sem ugotovil, da je obseg DB precej velik.

hoge_table | 350'000'000 |

350 milijonov zapisov. Zdi se, da je indeksacija delovala pravilno, samo zelo počasi.

Zahtevani zbir podatkov za mesec je znašal približno 12 000 000 zapisov. Zdi se, da je ekipa select vzela veliko časa in transakcija dolgo časa ni bila izvedena.

DB

V bistvu je to tabela, ki se vsak dan povečuje za približno 400 000 zapisov. Baza bi morala zbirati podatke samo za pretekli mesec, kar pomeni, da je bil izračun, da bo obvladala prav to količino podatkov, toda žal operacija rotate ni bila vklopljena.

Ta baza podatkov ni bila razvita z mojo pomočjo. Prevzel sem jo od drugega razvijalca, zato ostaja občutek, da gre za tehnično dolgovanje.

Prišel je trenutek, ko je obseg dnevno vstavljenih podatkov postal velik in končno dosegel mejnik. Predvideva se, da bi pri delu s tako velikimi količinami podatkov bilo treba te ločiti, toda tega žal ni bilo storjenega.

In tu sem stopil v igro.

Popravek

Bilo bi bolj smiselno zmanjšati samo DB in skrajšati čas obdelave, kot pa spremeniti samo logiko.

Situacija bi se morala znatno spremeniti, če izbrišem 300 milijonov zapisov, zato sem se odločil to storiti… Eh, mislil sem, da bo to zagotovo uspelo.

Dejanje 1

Potem ko sem pripravil zanesljivo varnostno kopijo, sem končno začel pošiljati poizvedbe.

「Pošiljanje poizvedbe」

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

「…」

「…」

„Hmm… Nič. Morda postopek traja predolgo?” – sem pomislil, a sem vseeno pogledal v grafano in videl, da se je obremenitev diska hitro povečevala.
„Tveganje“ – sem pomislil še enkrat in takoj ustavil poizvedbo.

Dejanje 2

Po analizi vsega sem spoznal, da je bila količina podatkov prevelika, da bi jo lahko odstranil vse naenkrat.

Odločil sem se, da napišem skripto, ki lahko izbriše približno 1.000.000 zapisov, in jo zagnal.

„izvajam skripto“

„Zdaj bo gotovo uspelo,“ – sem pomislil.

Dejanje 3

Druga metoda je delovala, a se je izkazala za zelo zamudno.
Da bi vse potekalo urejeno in brez nepotrebnega stresa, bi potreboval približno dva tedna. Vendar to, kar sem imel v mislih, ni ustrezalo zahtevam storitve, zato sem se moral od tega odmakniti.

Zato sem se odločil, da naredim to:

Kopiramo tabelo in jo preimenujemo.

Iz prejšnjega koraka sem spoznal, da odstranitev tako velike količine podatkov povzroča enako veliko obremenitev. Zato sem se odločil ustvariti novo tabelo od začetka s pomočjo vstavitev in vanjo prenesti podatke, ki sem jih nameraval izbrisati.

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

Če naredimo novo tabelo enake velikosti, kot je navedeno zgoraj, bi morala hitrost obdelave podatkov biti za 1/7 hitrejša.

Ko sem ustvaril tabelo in jo preimenoval, sem začel uporabljati to kot glavno tabelo. Zdaj, če bom izbrisal tabelo s 300 milijoni zapisov, bi vse moralo biti v redu.
Ugotovil sem, da truncate ali drop ustvarjata manjšo obremenitev kot delete, in se odločil uporabiti ta način.

Izvrševanje

「Pošiljanje poizvedbe」

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

「…」
「…」
„Hm…?“

Dejanje 4

Mislil sem, da bo prejšnja ideja delovala, a po pošiljanju poizvedbe za vstavitev se je pojavilo več napak. MySQL ne popušča.

Že sem bil tako utrujen, da sem začel razmišljati, da si tega ne želim več delati.

Pogledal sem in pomislil, da je mogoče za enkrat poizvedb za vstavitev preveč…
Poskusil sem poslati poizvedbo za vstavitev na količino podatkov, ki bi jih baza morala obdelati v enem dnevu. Uspelo je!

No in po tem nadaljujemo z pošiljanjem poizvedb na enako količino podatkov. Ker moramo odstraniti mesečno količino podatkov, ponovimo to operacijo približno 35-krat.

Preimenovanje tabele

Tukaj mi je bila sreča naklonjena: vse je potekalo gladko.

Alerti so izginili.

Hitrost obdelave pošiljk se je povečala.

V preteklosti je ta postopek trajal približno eno uro, zdaj pa traja približno 2 minuti.

Ko sem se prepričal, da so vse težave rešene, sem izbrisal 300 milijonov zapisov. Izbrisal sem tabelo in se počutil kot ponovno rojen.

Povzetek

Zavedel sem se, da je bila pri obdelavi v paketih izpuščena rotacija, kar je predstavljalo glavno težavo. Takšna napaka v arhitekturi vodi do prazne izgube časa.

Ali ste kdaj pomislili na obremenitev ob replikaciji podatkov, ko brišete zapise iz baze? Ne obremenjujmo MySQL.

Tisti, ki se dobro spoznajo na podatkovne baze, se s takšno težavo zagotovo ne bodo soočili. Upam, da je bil ta članek koristen ostalim.

Hvala za branje!

Zelo bi nas razveselilo, če bi nam povedali, ali vam je bil ta članek všeč, ali je bil prevod jasen in ali je bil koristen?

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster