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

Průvodce pro figuríny zamykáním v innodb

Zde jsou mé poznámky z práce s podporou MySQL na nedávném podivném problému se zamykáním (verze 5.1.37):

Všechny řádky a položky rejstříku, které projdou, aby se dostali ke změněným řádkům, budou uzamčeny. Je pokryta na adrese:

http://dev.mysql.com/doc /refman/5.1/en/innodb-locks-set.html

"Zamykací čtení, UPDATE nebo DELETE obecně nastavují zámky záznamů na každém záznamu indexu, který je skenován při zpracování příkazu SQL. Nezáleží na tom, zda jsou v příkazu podmínky WHERE, které by vyloučily řádek. InnoDB ano nepamatuje si přesnou podmínku WHERE, ale ví pouze, které rozsahy indexů byly naskenovány... Pokud nemáte žádné indexy vhodné pro váš příkaz a MySQL musí pro zpracování příkazu skenovat celou tabulku, každý řádek tabulky se uzamkne, což v turn zablokuje všechna vložení ostatních uživatelů do tabulky."

To je. Řešením, které je často užitečné, je:

AKTUALIZUJTE libovolnou možnost nastavit cokoli na něco, kde je primární klíč (vyberte primární klíč z kterékoli možnosti, kde omezení pořadí podle primárního klíče);

Vnitřní výběr se nemusí zamykat a aktualizace pak bude mít méně práce s aktualizací. Pořadí podle klauzule zajišťuje, že aktualizace bude provedena v pořadí primárního klíče, aby odpovídalo fyzickému pořadí InnoDB, což je nejrychlejší způsob, jak to provést.

Pokud se jedná o velký počet řádků, jako ve vašem případě, může být lepší uložit výsledek výběru do dočasné tabulky s přidaným sloupcem příznaku. Poté vyberte z dočasné tabulky, kde není nastaven příznak, abyste získali každou dávku. Spusťte aktualizace s limitem řekněme 1000 nebo 10000 a nastavte příznak pro dávku po aktualizaci. Limity udrží míru uzamčení na tolerovatelné úrovni, zatímco výběrová práce bude muset být provedena pouze jednou. Po každé dávce se zavázat k uvolnění zámků.

Tuto práci můžete také urychlit provedením vybraného součtu neindexovaného sloupce před provedením každé dávky aktualizací. Tím se načtou datové stránky do oblasti vyrovnávacích pamětí, aniž by došlo k uzamčení. Pak bude uzamčení trvat kratší dobu, protože nedojde k žádnému čtení disku.

To není vždy praktické, ale když je, může to být velmi užitečné. Pokud to nemůžete udělat v dávkách, můžete alespoň zkusit nejprve vybrat, aby se data předem načetla, pokud jsou dostatečně malá, aby se vešla do zásobníku vyrovnávací paměti.

Pokud je to možné, použijte režim izolace transakcí READ COMMITTED. Viz:

http://dev.mysql.com/doc/refman /5.1/cs/set-transaction.html

Chcete-li dosáhnout tohoto omezeného zamykání, vyžaduje použití binárního protokolování založeného na řádcích (spíše než výchozího binárního protokolování založeného na příkazech).

Dva známé problémy:

  1. Poddotazy mohou být někdy méně než ideálně optimalizovány. V tomto případě se jednalo o nežádoucí závislý poddotaz – můj návrh na použití poddotazu se proto ukázal jako neužitečný ve srovnání s alternativou v tomto případě.

  2. Odstranění a aktualizace nemají stejný rozsah plánů dotazů jako příkazy select, takže je někdy těžké je správně optimalizovat bez měření výsledků, abyste přesně zjistili, co dělají.

Obojí se postupně zlepšuje. Tato chyba je jedním z příkladů, kdy jsme právě vylepšili dostupné optimalizace pro aktualizaci, ačkoli změny jsou významné a stále prochází kontrolou kvality, abychom se ujistili, že to nebude mít žádné velké nepříznivé účinky:

http://bugs.mysql.com/bug.php?id=36569




  1. Jak použít opak BETWEEN v dotazu MySQL?

  2. Vztah One-to-Many v MySQL – jak vytvořit model?

  3. jak se přihlásit do mysql a dotazovat se na databázi z linuxového terminálu

  4. Výjimka syntaxe na spouštěči s více příkazy s MySQL a JDBC