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.