Povestea ștergerii fizice a 300 de milioane de înregistrări în MySQL

Introducere

Buna ziua. Sunt ningenMe, dezvoltator web.

După cum spune titlul, povestea mea este povestea ștergerii fizice a 300 de milioane de înregistrări în MySQL.

Am devenit interesat de asta, așa că am decis să fac un memento (instrucțiuni).

Acasă - Alertă

Serverul batch pe care îl folosesc și îl întrețin are un proces regulat care colectează datele din ultima lună din MySQL o dată pe zi.

De obicei, acest proces este finalizat în aproximativ 1 oră, dar de data aceasta nu s-a finalizat timp de 7 sau 8 ore, iar alerta nu a încetat să apară...

Căutând un motiv

Am încercat să repornesc procesul și să mă uit la jurnalele, dar nu am văzut nimic în neregulă.
Interogarea a fost indexată corect. Dar când m-am gândit la ce nu mergea bine, mi-am dat seama că dimensiunea bazei de date este destul de mare.

hoge_table | 350'000'000 |

350 de milioane de înregistrări. Indexarea părea să funcționeze corect, doar foarte lentă.

Colectarea de date necesară pe lună a fost de aproximativ 12 de înregistrări. Se pare că comanda select a durat mult și tranzacția nu a fost executată mult timp.

DB

În esență, este un tabel care crește cu aproximativ 400 de intrări în fiecare zi. Baza de date trebuia să colecteze date doar pentru ultima lună, prin urmare, era de așteptat să reziste exact la această cantitate de date, dar, din păcate, operația de rotație nu a fost inclusă.

Această bază de date nu a fost dezvoltată de mine. L-am preluat de la un alt dezvoltator, așa că încă se simțea ca o datorie tehnică.

A venit un moment în care volumul de date introduse zilnic a devenit mare și, în sfârșit, a atins limita. Se presupune că atunci când lucrați cu o cantitate atât de mare de date, ar fi necesară separarea acestora, dar acest lucru, din păcate, nu s-a făcut.

Și apoi am intrat în acțiune.

Corecţie

Era mai rațional să se reducă dimensiunea bazei de date în sine și să se reducă timpul de procesare decât să se schimbe logica în sine.

Ситуация должна значительно измениться, если стереть 300 миллионов записей, поэтому я решил так и сделать… Эх, я думал, что это точно сработает.

Acțiunea 1

După ce am pregătit o copie de rezervă de încredere, am început în sfârșit să trimit solicitări.

「Trimiterea unei cereri」

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

„…”

„…”

„Hmm... Niciun răspuns. Poate că procesul durează mult?” — M-am gândit, dar pentru orice eventualitate, m-am uitat la grafana și am văzut că încărcarea discului crește foarte repede.
„Periculos”, m-am gândit din nou și am oprit imediat cererea.

Acțiunea 2

După ce am analizat totul, mi-am dat seama că volumul de date era prea mare pentru a șterge totul dintr-o dată.

Am decis să scriu un script care ar putea șterge aproximativ 1 de înregistrări și l-am lansat.

„Implementez scenariul”

„Acum asta va funcționa cu siguranță”, m-am gândit.

Acțiunea 3

A doua metodă a funcționat, dar s-a dovedit a fi foarte laborioasă.
Pentru a face totul cu grijă, fără nervi inutile, ar dura aproximativ două săptămâni. Dar totuși, acest scenariu nu a îndeplinit cerințele de serviciu, așa că a trebuit să ne îndepărtăm de el.

Deci, iată ce am decis să fac:

Copiați tabelul și redenumiți-l

De la pasul anterior, mi-am dat seama că ștergerea unei cantități atât de mari de date creează o încărcare la fel de mare. Așa că am decis să creez un nou tabel de la zero folosind insert și să mut datele pe care urma să le șterg în el.

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

Dacă faceți noul tabel la aceeași dimensiune ca mai sus, viteza de procesare a datelor ar trebui, de asemenea, să devină cu 1/7 mai rapidă.

După ce am creat tabelul și l-am redenumit, am început să îl folosesc ca tabel principal. Acum, dacă renunț la masa cu 300 de milioane de înregistrări, totul ar trebui să fie bine.
Am aflat că trunchiarea sau drop creează mai puțină suprasarcină decât ștergerea și am decis să folosesc această metodă.

execuție

「Trimiterea unei cereri」

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

„…”
„…”
"Ei...?"

Acțiunea 4

Am crezut că ideea anterioară va funcționa, dar după trimiterea cererii de inserare, au apărut mai multe erori. MySQL nu este iertător.

Eram deja atât de obosită încât am început să cred că nu mai vreau să fac asta.

Am stat și m-am gândit și mi-am dat seama că poate au fost prea multe interogări de inserare pentru o singură dată...
Am încercat să trimit o cerere de inserare pentru cantitatea de date pe care baza de date ar trebui să o prelucreze în 1 zi. S-a întâmplat!

Ei bine, după aceea continuăm să trimitem solicitări pentru aceeași cantitate de date. Deoarece trebuie să eliminăm datele pentru o lună, repetăm ​​această operațiune de aproximativ 35 de ori.

Redenumirea unui tabel

Aici norocul a fost de partea mea: totul a decurs bine.

Alerta a dispărut

Viteza de procesare a lotului a crescut.

Anterior acest proces dura aproximativ o oră, acum durează aproximativ 2 minute.

După ce am fost sigur că toate problemele au fost rezolvate, am scăpat 300 de milioane de înregistrări. Am șters tabelul și m-am simțit renăscut.

rezumat

Mi-am dat seama că procesarea prin rotație lipsește în procesarea lot și asta era principala problemă. Acest tip de eroare arhitecturală duce la o pierdere de timp.

Vă gândiți la încărcarea în timpul replicării datelor atunci când ștergeți înregistrările din baza de date? Să nu supraîncărcăm MySQL.

Cei care cunosc bine bazele de date cu siguranță nu se vor confrunta cu o astfel de problemă. Pentru voi restul, sper că acest articol a fost util.

Multumesc pentru lectura!

Vom fi foarte bucuroși dacă ne spui dacă ți-a plăcut acest articol, dacă traducerea este clară, dacă ți-a fost de folos?

Sursa: www.habr.com

Adauga un comentariu