sql >> Databáze >  >> RDS >> Mysql

Vytvořte index na obrovském produkčním stole MySQL bez zamykání tabulky

[2017] Aktualizace:MySQL 5.6 podporuje online aktualizace indexů

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes

V MySQL 5.6 a vyšší zůstává tabulka dostupná pro operace čtení a zápisu, zatímco je index vytvářen nebo rušen. Příkaz CREATE INDEX nebo DROP INDEX skončí až po dokončení všech transakcí, které přistupují k tabulce, takže počáteční stav indexu odráží nejnovější obsah tabulky. Dříve úpravy tabulky při vytváření nebo rušení indexu obvykle vedly k uváznutí, které zrušilo příkazy INSERT, UPDATE nebo DELETE v tabulce.

[2015] Aktualizace zápisů bloků indexů tabulky v MySQL 5.5

Z výše uvedené odpovědi:

"Pokud používáte verzi vyšší než 5.1, indexy jsou vytvořeny, když je databáze online. Takže se nemusíte bát, že nepřerušíte používání produkčního systému."

Toto je ****FALSE**** (alespoň pro tabulky MyISAM / InnoDB, což je to, co používá 99,999 % lidí. Clustered Edition je jiná.)

Provádění operací UPDATE na stole se ZABLOKUJE při vytváření indexu. MySQL je v tomhle (a několika dalších věcech) opravdu, opravdu hloupé.

Testovací skript:

(   
  for n in {1..50}; do
    #(time mysql -uroot -e 'select  * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
    (time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
  done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'

Můj server (InnoDB):

Server version: 5.5.25a Source distribution

Výstup (všimněte si, jak 6. operace blokuje přibližně 400 ms, které trvá dokončení aktualizace indexu):

 1  real    0m0.009s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.012s
 5  real    0m0.009s
Index Update - START
Index Update - FINISH
 6  real    0m0.388s
 7  real    0m0.009s
 8  real    0m0.009s
 9  real    0m0.009s
10  real    0m0.009s
11  real    0m0.009s

Vs operace čtení, které neblokují (prohoďte komentář řádku ve skriptu):

 1  real    0m0.010s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.010s
 5  real    0m0.009s
Index Update - START
 6  real    0m0.010s
 7  real    0m0.010s
 8  real    0m0.011s
 9  real    0m0.010s
...
41  real    0m0.009s
42  real    0m0.010s
43  real    0m0.009s
Index Update - FINISH
44  real    0m0.012s
45  real    0m0.009s
46  real    0m0.009s
47  real    0m0.010s
48  real    0m0.009s

Aktualizace schématu MySQL bez prostojů

Zatím znám pouze jeden způsob, jak aktualizovat schéma MySql a netrpět výpadkem dostupnosti. Kruhové předlohy:

  • Na hlavním A běží vaše databáze MySQL
  • Uveďte Master B do provozu a nechte jej replikovat zápisy z Master A (B je otrokem A)
  • Proveďte aktualizaci schématu na hlavním serveru B. Během upgradu dojde ke zpoždění
  • Nechte mistra B dohnat. Invariant:Vaše změna schématu MUSÍ být schopna zpracovávat příkazy replikované ze schématu downversion. Změny indexování se kvalifikují. Jednoduché přidání sloupců se obvykle hodí. Odebrat sloupec? asi ne.
  • ATOMICKY vyměňte všechny klienty z Master A na Master B. Pokud chcete být v bezpečí (věřte mi, ano), měli byste zajistit, aby poslední zápis do A byl replikován do B PŘED B provede svůj první zápis. Pokud povolíte souběžné zápisy do 2+ masterů, ... budete lépe rozumět replikaci MySQL na HLOUBKOVÉ úrovni nebo se vydáte do světa bolesti. Extrémní bolest. Jako, máte sloupec, který je AUTOINCREMENT??? jste v háji (pokud nepoužíváte sudá čísla na jednom masteru a lichá na druhém). Nedůvěřujte replikaci MySQL, že „udělá správnou věc“. NENÍ to chytré a nezachrání vás to. Je to jen o něco méně bezpečné než kopírování binárních protokolů transakcí z příkazového řádku a jejich ruční přehrávání. Přesto lze odpojení všech klientů od starého hlavního serveru a jejich přepnutí do nového hlavního serveru provést během několika sekund, což je mnohem rychleji než čekání na mnohahodinový upgrade schématu.
  • Nyní je Mistr B vaším novým mistrem. Máte nové schéma. Život je dobrý. Dát si pivo; to nejhorší je za námi.
  • Opakujte proces s mistrem A a upgradujte jeho schéma tak, aby se stal vaším novým sekundárním mistrem, připraveným převzít řízení v případě, že váš primární mistr (nyní mistr B) ztratí energii nebo se prostě vzchopí a zemře na vás.
  • li>

Snadný způsob aktualizace schématu to není. Funkční v seriózním výrobním prostředí; Ano to je. Prosím, prosím, prosím, pokud existuje jednodušší způsob, jak přidat index do tabulky MySQL bez blokování zápisů, dejte mi vědět.

Google mě přivedl k tomuto článku který popisuje podobnou techniku. Ještě lepší je, že doporučují pít ve stejném bodě postupu (Všimněte si, že jsem svou odpověď napsal před přečtením článku)!

Percona's pt-online-schema-change

článek Výše jsem odkazoval na řeči o nástroji, pt -online-schema-change , který funguje následovně:

  • Vytvořte novou tabulku se stejnou strukturou jako původní.
  • Aktualizujte schéma v nové tabulce.
  • Přidejte spouštěč do původní tabulky, aby byly změny synchronizovány s kopií
  • Kopírujte řádky v dávkách z původní tabulky.
  • Přesuňte původní tabulku z cesty a nahraďte ji novou.
  • Zrušte starý stůl.

Sám jsem nástroj nikdy nezkoušel. YMMV

RDS

Momentálně používám MySQL prostřednictvím RDS společnosti Amazon . Je to opravdu šikovná služba, která zabalí a spravuje MySQL, umožní vám přidávat nové repliky čtení pomocí jediného tlačítka a transparentně upgradovat databázi napříč hardwarovými SKU. Je to opravdu pohodlné. Nezískáte SUPER přístup k databázi, takže nemůžete s replikací přímo makat (je to požehnání nebo prokletí?). Můžete však použít Přečtěte si Propagaci replik abyste provedli změny schématu na slave pouze pro čtení, pak povyšte tohoto slave, aby se stal vaším novým pánem. Přesně stejný trik, jaký jsem popsal výše, jen je mnohem snazší provést. Stále vám příliš nepomohou s přeříznutím. Musíte znovu nakonfigurovat a restartovat aplikaci.



  1. Jak mohu přidat sloupec, který nepovoluje hodnoty null v databázi Postgresql?

  2. Vygenerujte řadu dat – jako vstup použijte typ data

  3. Systémové databáze SQL Server – údržba Tempdb

  4. Jak mohu provést SELECT DISTINCT na všech polích kromě BLOB?