Príbeh o fyzickom odstránení 300 miliónov záznamov v MySQL

Úvod

Ahoj. Som ningenMe, webový vývojár.

Ako naznačuje názov, môj príbeh je príbehom o fyzickom odstránení 300 miliónov záznamov v MySQL.

Zaujal ma tento problém, a tak som sa rozhodol vytvoriť poznámku (návod).

Začiatok — Alert

V dávkovom serveri, ktorý používam a spravujem, je pravidelný proces, ktorý každý deň zbiera údaje za posledný mesiac z MySQL.

Zvyčajne tento proces trvá približne 1 hodinu, ale tentoraz sa nedokončil 7 alebo 8 hodín a upozornenie sa nezastavilo...

Hľadanie príčiny

Snažil som sa reštartovať proces, pozrieť sa na logy, ale nič vážne som nevidel.
Dotaz bol správne indexovaný. Ale keď som uvažoval, čo sa deje zle, uvedomil som si, že objem DB je pomerne veľký.

hoge_table | 350'000'000 |

350 miliónov záznamov. Zdá sa, že indexovanie fungovalo správne, iba veľmi pomaly.

Požadovaný zber údajov za mesiac bol približne 12 000 000 záznamov. Zdá sa, že príkaz select trval dlho a transakcia sa dlho nevykonávala.

DB

V podstate ide o tabuľku, ktorá sa každý deň zvyšuje o približne 400 000 záznamov. Databáza mala zbierať údaje len za posledný mesiac, a preto sa predpokladalo, že zvládne tento objem údajov, ale žiaľ, operácia rotate nebola zapnutá.

Túto databázu nevytvoril som ja. Prevzal som ju od iného vývojára, takže zostal pocit technického dlhu.

Prišiel moment, keď objem denne vkladaných údajov sa stal veľkým a nakoniec dosiahol svoj limit. Predpokladá sa, že pri práci s takým veľkým objemom údajov by ich malo byť potrebné rozdeľovať, ale to, žiaľ, nebolo vykonané.

A tu som zasadol do hry ja.

Oprava

Bolo rozumnejšie zmenšiť samotnú databázu a skrátiť čas jej spracovania, než meniť samotnú logiku.

Situácia by sa mala výrazne zmeniť, ak vymažeme 300 miliónov záznamov, takže som sa rozhodol tak spraviť... Ach, myslel som si, že to určite zafunguje.

Akcia 1

Po príprave spoľahlivej zálohy som konečne začal posielať požiadavky.

「Odoslanie požiadavky」

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

「…」

「…」

“Hm… Odpovede niet. Možno proces trvá dlho?” — pomyslel som si, ale pre istotu som sa pozrel do grafana a videl, že zaťaženie disku veľmi rýchlo rástlo.
„Nebezpečne“ — pomyslel som si znova a hneď som zastavil požiadavku.

Akcia 2

Analyzovaním všetkého som zistil, že objem dát bol príliš veľký na to, aby som všetko vymazal naraz.

Rozhodol som sa napísať skript, ktorý dokáže vymazávať asi 1 000 000 záznamov a spustil som ho.

「realizujem skript」

„Teraz to určite zafunguje,“ pomyslel som si.

Akcia 3

Druhý spôsob zafungoval, ale bol veľmi pracný.
Aby som všetko urobil opatrne, bez zbytočného stresu, trvalo by to približne dva týždne. Avšak tento scenár nevyhovoval požiadavkám služby, a preto som sa musel od neho vzdať.

Takže, toto je to, čo som sa rozhodol urobiť:

Skopírujeme tabuľku a premenováme ju

Z predchádzajúceho kroku som pochopil, že vymazanie takého veľkého objemu dát vytvára takú istú veľkú záťaž. Preto som sa rozhodol vytvoriť novú tabuľku od nuly pomocou insert a presunúť do nej dáta, ktoré som chcel vymazať.

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

Ak vytvoríte novú tabuľku rovnakej veľkosti, akú som uviedol vyššie, rýchlosť spracovania dát by mala byť aj 1/7 rýchlejšia.

Potom, čo som vytvoril tabuľku a premenoval ju, som začal používať ju ako hlavnú (master) tabuľku. Teraz, ak vymažem tabuľku so 300 miliónmi záznamov, malo by to byť v poriadku.
Zistil som, že truncate alebo drop spôsobujú menšiu záťaž ako delete, a rozhodol som sa použiť tento spôsob.

Vykonávanie

「Odoslanie požiadavky」

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

「…」
「…」
„eh…?“

Akcia 4

Myslel som, že predchádzajúci nápad zafunguje, ale po odoslaní požiadavky insert sa objavila množstvo chýb. MySQL nešetrí.

Bol som už tak unavený, že som začal myslieť, že už to nechcem robiť.

Posadil som sa a premýšľal a uvedomil som si, že možno pre jedenkrát bolo požiadaviek insert príliš veľa...
Skúsil som poslať požiadavku insert na objem dát, ktoré by mala databáza spracovať za 1 deň. Podarilo sa!

A potom pokračujeme v zasielaní požiadaviek na rovnaký objem dát. Keďže mám odstrániť mesačný objem údajov, opakujem túto operáciu približne 35-krát.

Premenovanie tabuľky

Tu mi šťastie stálo na strane: všetko prebehlo hladko.

Alert zmizli

Rýchlosť dávkového spracovania vzrástla.

Skôr tento proces trval približne hodinu, teraz trvá asi 2 minúty.

Keď som sa uistil, že všetky problémy sú vyriešené, odstránil som 300 miliónov záznamov. Vymazal som tabuľku a cítil som sa ako znovuzrodený.

Zhrnutie

Uvedomil som si, že v dávkovom spracovaní bola vynechaná rotácia spracovania, a to bola hlavná príčina problému. Takáto chyba v architektúre vedie k zbytočnému plytvaniu časom.

Zamýšľate nad záťažou pri replikácii údajov, keď odstraňujete záznamy z databázy? Poďme nepreťažovať MySQL.

Tí, ktorí sa dobre vyznajú v databázach, sa s takýmto problémom určite nestretnú. Dúfam, že tento článok bol užitočný pre ostatných.

Ďakujeme za prečítanie!

Veľmi nás poteší, ak nám poviete, či sa vám tento článok páčil, či bol preklad zrozumiteľný a či bol pre vás užitočný.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster