Om samtidighedsproblemerne har du en 'let' måde at forhindre eventuelle samtidighedsproblemer i den anden metode, skal du i din transaktion udføre et valg på artiklerlinjen (
Med de nye standard isolationsniveauer, uden selv at bruge serialiseringsniveau i transaktionen, ville du ikke se nogen samtidig indsættelse på afstemningsbordet før slutningen af din transaktion. Så din SUM bør forblive sammenhængende eller ligne sammenhængende . Men hvis en samtidig transaktion indsætter en stemme på samme artikel og begår før dig (og denne 2. kan ikke se din indsættelse), vil den sidste transaktion, der skal begås, overskrive tælleren, og du mister 1 stemme. Så udfør en rækkelås på artiklen ved at bruge en vælg før (og gør dit arbejde i en transaktion, selvfølgelig). Det er nemt at teste, åbn 2 interaktive sessioner på MySQL og start transaktioner med BEGIN.
Hvis du bruger triggeren, er du som standard i en transaktion. Men jeg synes, du skal udføre valget på artikeltabellen lige så godt for at lave en implicit rækkelås for samtidige triggere, der kører (sværere at teste).
- Glem ikke at slette triggere.
- Glem ikke opdateringsudløsere.
- Hvis du ikke bruger triggere og stayin-kode, skal du passe på, at hver indsæt/slet/opdater forespørgsel på afstemning skal udføre en rækkelås på den tilsvarende artikel før i transaktionen. Det er ikke særlig svært at glemme en.
Sidste punkt:lav sværere transaktioner, før du starter transaktionen, brug:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
På denne måde behøver du ikke rækkelåse på artikler, MySQL vil opdage, at en potentiel skrivning på samme række forekommer og vil blokere de andres transaktion, indtil du er færdig. Men brug ikke noget, du har beregnet fra en tidligere anmodning . Opdateringsforespørgslen venter på en låsefrigivelse på artikler, når låsen frigives af den 1. transaktion COMMIT
beregningen af SUM
skal gøres igen for at tælle. Så opdateringsforespørgslen bør indeholde SUM
eller lav en tilføjelse.
update articles set nb_votes=(SELECT count(*) from vote) where id=2;
Og her vil du se, at MySQL er smart, et dødvande detekteres, hvis 2 transaktioner forsøger at gøre dette, mens indsættelse er blevet udført på samme tid. I serialiseringsniveauer har jeg ikke fundet en måde at opnå en forkert værdi med :
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;
Men vær klar til at håndtere brud på transaktionen, som du skal lave om.