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

Jak jsou tabulky innodb uzamčeny, když je zpracován trigger ON INSERT?

Ohledně problémů se souběžností máte 'snadné' způsob, jak předejít jakýmkoli problémům se souběhem ve 2. metodě, v rámci transakce proveďte výběr na řádku článků (For update je nyní implicitní). Jakákoli souběžná vložka na stejném článku nebude schopna získat stejný zámek a počká na vás.

S novými výchozími úrovněmi izolace byste bez použití úrovně serializace v transakci neviděli žádné souběžné vložení v tabulce hlasování až do konce transakce. Váš SUM by tedy měl zůstat koherentní nebo jako koherentní vypadat . Ale pokud souběžná transakce vloží hlas pro stejný článek a odevzdá před vámi (a tato 2. neuvidí vaši vložení), poslední transakce k potvrzení přepíše počítadlo a vy ztratíte 1 hlas. Proveďte tedy u článku zámek řádku pomocí výběru před (a samozřejmě dělat svou práci v transakci). Je snadné otestovat, otevřít 2 interaktivní relace na MySQL a zahájit transakce pomocí BEGIN.

Pokud použijete spouštěč, jste ve výchozím nastavení v transakci. Ale myslím si, že byste měli provést také výběr v tabulce článků, abyste vytvořili implicitní zámek řádku pro souběžné spouštěče (obtížnější test).

  • Nezapomeňte smazat spouštěče.
  • Nezapomeňte na spouštěče aktualizace.
  • Pokud nepoužíváte spouštěče a kód setrvání v kódu, buďte opatrní při každém vložení/smazání/aktualizaci dotazu na hlasování by měl provést zámek řádku u odpovídajícího článku před v transakci. Není těžké na jednu zapomenout.

Poslední bod:provádějte těžší transakce, před zahájením transakce použijte:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Tímto způsobem nepotřebujete zámky řádků na článcích, MySQL zjistí, že dojde k potenciálnímu zápisu na stejný řádek, a zablokuje ostatní transakce, dokud nedokončíte. Nepoužívejte však něco, co jste vypočítali z předchozího požadavku . Aktualizační dotaz bude čekat na uvolnění zámku u článků, když je zámek uvolněn 1. transakcí COMMIT výpočet SUM by mělo být provedeno znovu počítat. Aktualizační dotaz by tedy měl obsahovat SUM nebo doplňte.

update articles set nb_votes=(SELECT count(*) from vote) where id=2; 

A zde uvidíte, že MySQL je chytré, zablokování je detekováno, pokud se o to pokoušejí 2 transakce, zatímco vložení bylo provedeno současně. V úrovních serializace jsem nenašel způsob, jak získat špatnou hodnotu pomocí :

   SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
   BEGIN;
       insert into vote (...
       update articles set nb_votes=(
         SELECT count(*) from vote where article_id=xx
       ) where id=XX;
    COMMIT;

Ale buďte připraveni zvládnout narušení transakce, kterou musíte opakovat.



  1. Kdy použít SQL_NO_CACHE

  2. MySQL Query – získejte záznamy na základě aktuálního data

  3. Datum Java SQL je posunuto o 1 den

  4. Jak filtrovat (nebo nahradit) znaky unicode, které by v UTF-8 zabraly více než 3 bajty?