A fizikai törlés története 300 millió MySQL rekordról

Bevezetés

Helló. Én ningenMe vagyok, webfejlesztő.

Ahogy a cím is mondja, a történetem a MySQL-ben található 300 millió rekord fizikális törléséről szól.

Érdekelt a téma, ezért úgy döntöttem, hogy készítek egy emlékeztetőt (utasítást).

Kezdet — Figyelmeztetés

A köteges szerveren, amelyet használok és karbantartok, rendelkezik egy rendszeres folyamattal, amely naponta egyszer összegyűjti az elmúlt hónap adatokat a MySQL-ből.

Ez a folyamat általában körülbelül 1 órán belül befejeződik, de ez alkalommal 7 vagy 8 órát is eltartott, és a figyelmeztetés folyamatosan megjelent...

Az ok kutatása

Megpróbáltam újraindítani a folyamatot, megnéztem a naplókat, de semmi különösebb problémát nem találtam.
A lekérdezés helyesen volt indexelve. De amikor elgondolkodtam azon, hogy mi lehet a probléma, rájöttem, hogy az adatbázis eléggé nagy.

hoge_table | 350'000'000 |

350 millió rekord. Úgy tűnik, hogy az indexelés helyesen működött, csak nagyon lassan.

A hónapra szükséges adatszám körülbelül 12 000 000 rekord volt. Úgy tűnik, hogy a select művelet sok időt vett igénybe, és a tranzakció hosszú ideig nem futott le.

DB

Lényegében ez egy táblázat, amely naponta körülbelül 400 000 rekorddal nő. Az adatbázisnak csak az elmúlt hónap adatainak összegyűjtését kellett volna végeznie, tehát azt a mennyiséget kellett volna elbírnia, de sajnos a rotate művelet nem volt aktiválva.

Ezt az adatbázist nem én fejlesztettem ki. Egy másik fejlesztőtől kaptam át, ezért úgy érzem, hogy ez technikai adósság.

Eljött az a pillanat, amikor a napi beszúrt adatok mennyisége nagy lett és végül elérte a határt. Úgy tűnik, hogy egy ilyen nagy adatmennyiséggel való munka esetén szét kellett volna választani azokat, de sajnos ez nem történt meg.

Akkor én léptem a színre.

Hibaelhárítás

Racionálisabb volt csökkenteni az adatbázist magát, és csökkenteni a feldolgozási időt, mint megváltoztatni a logikát.

A helyzet jelentősen megváltozik, ha 300 millió rekordot törlünk, ezért úgy döntöttem, hogy megteszem... Hát, azt hittem, hogy ez biztosan működni fog.

1. lépés

Miután elkészítettem egy megbízható biztonsági másolatot, végre elkezdtem küldeni a lekérdezéseket.

„Lekérdezés küldése”

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

「…」

「…」

„Hmmm... Nincs válasz. Talán a folyamat sok időt vesz igénybe?” – gondoltam, de minden esetre megnéztem a grafanát, és láttam, hogy a lemezterhelés nagyon gyorsan növekszik.
„Veszélyes” – gondoltam, és rögtön megállítottam a lekérdezést.

Cselekvés 2

Mindent megvizsgálva rájöttem, hogy az adatok mennyisége túl nagy volt ahhoz, hogy egyszerre töröljem őket.

Egy olyan szkriptet írtam, amely körülbelül 1 000 000 bejegyzést képes törölni, és elindítottam.

「szkriptet írok」

„Most már biztosan működni fog” – gondoltam.

Cselekvés 3

A második módszer működött, de nagyon időigényesnek bizonyult.
Ahhoz, hogy mindent pontosan, idegeskedés nélkül csináljak, körülbelül két hétre lett volna szükségem. De ez a forgatókönyv nem felelt meg a szolgáltatási követelményeknek, ezért el kellett állnom tőle.

Ezért ez az, amit döntöttem:

Másoljuk a táblázatot és átnevezzük.

Az előző lépésből rájöttem, hogy egy ilyen nagy mennyiségű adat törlése ugyanakkora terhelést okoz. Ezért úgy döntöttem, új táblát hozok létre a nulláról INSERT-tel, és abba áthelyezem az adatokat, amelyeket törölni akartam.

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

Ha az új táblát a fent jelzett méretben készítjük el, az adatfeldolgozás sebessége is 1/7-el gyorsabbá kell, hogy váljon.

A táblát létrehozva és átnevezve, én a master (fő) táblaként kezdtem használni. Most, ha törlöm a 300 millió bejegyzést tartalmazó táblát, minden rendben kell, hogy legyen.
Megtanultam, hogy a TRUNCATE vagy DROP kisebb terhelést okoz, mint a DELETE, és úgy döntöttem, hogy ezt a módszert alkalmazom.

Végrehajtás

„Lekérdezés küldése”

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

「…」
「…」
„Hát…?”

Cselekvés 4

Azt hittem, az előző ötlet működni fog, de a lekérdezés elküldése után sok hiba történt. A MySQL nem kegyelmez.

Már annyira fáradt voltam, hogy kezdtem úgy érezni, nem akarom ezt tovább csinálni.

Néhány percet töltöttem azzal, hogy átgondoljam, és rájöttem, talán egy alkalomra túl sok INSERT lekérdezést küldtem…
Megpróbáltam egy INSERT lekérdezést elküldeni a mennyiségre, amelyet az adatbázisnak egy nap alatt kell feldolgoznia. Sikerült!

Nos, utána folytatjuk a lekérdezések küldését ugyanazzal a mennyiséggel. Mivel el kell távolítanunk egy hónapnyi adatot, ezt a műveletet körülbelül 35 alkalommal megismételjük.

A táblázat átnevezése

Itt a szerencse az én oldalamon állt: minden simán ment.

Az alert eltűnt.

A csomagfeldolgozás sebessége megnőtt.

Korábban ez a folyamat körülbelül egy órát vett igénybe, most körülbelül 2 percig tart.

Miután megbizonyosodtam arról, hogy minden probléma megoldódott, ledobtam 300 millió rekordot. Töröltem a táblázatot, és újjászületettnek éreztem magam.

Összegzés

Rájöttem, hogy a kötegelt feldolgozás során elmaradt a forgatás feldolgozása, és ennek ez volt a fő problémája. Az ilyen architektúrából adódó hiba időpazarláshoz vezet.

Gondolkodtál már a terhelésről az adatok replikálásakor, amikor rekordokat törölsz az adatbázisból? Ne terheljük túl a MySQL-t.

Azok, akik jól értenek az adatbázisokhoz, biztosan nem találkoznak ezzel a problémával. A többieknek remélem, hasznos volt ez a cikk.

Köszönöm a figyelmet!

Nagyon örülnénk, ha elmondanád, hogy tetszett ez a cikk, érthető volt-e a fordítás, és hasznos volt-e számodra?

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster