sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL og ActiveRecord undervælges til race tilstand

Dine muligheder er:

  • Kør i SERIALIZABLE isolation. Indbyrdes afhængige transaktioner vil blive afbrudt ved commit som havende en serialiseringsfejl. Du vil få masser af fejllog-spam, og du vil gøre mange genforsøg, men det vil fungere pålideligt.

  • Definer en UNIQUE begrænsning og prøv igen ved fejl, som du bemærkede. Samme problemer som ovenfor.

  • Hvis der er et overordnet objekt, kan du SELECT ... FOR UPDATE det overordnede objekt, før du udfører dit max forespørgsel. I dette tilfælde skal du SELECT 1 FROM bar WHERE bar_id = $1 FOR UPDATE . Du bruger bar som en lås til alle foo s med det bar_id . Du kan så vide, at det er sikkert at fortsætte, så længe hver forespørgsel, der øger din tæller, gør dette pålideligt. Dette kan fungere ganske godt.

    Dette foretager stadig en samlet forespørgsel for hvert opkald, hvilket (pr. næste mulighed) er unødvendigt, men det spammer i det mindste ikke fejlloggen som ovenstående muligheder.

  • Brug et bordbord. Det er, hvad jeg ville gøre. Enten i bar , eller i en sidetabel som bar_foo_counter , anskaffe et række-id ved hjælp af

    UPDATE bar_foo_counter SET counter = counter + 1
    WHERE bar_id = $1 RETURNING counter
    

    eller den mindre effektive mulighed, hvis dit framework ikke kan håndtere RETURNING :

    SELECT counter FROM bar_foo_counter
    WHERE bar_id = $1 FOR UPDATE;
    
    UPDATE bar_foo_counter SET counter = $1;
    

    Derefter i samme transaktion , brug den genererede tællerrække til number . Når du forpligter, tæller tabelrækken for den bar_id bliver låst op til den næste forespørgsel, der skal bruges. Hvis du ruller tilbage, kasseres ændringen.

Jeg anbefaler tællertilgangen ved at bruge en dedikeret sidetabel til tælleren i stedet for at tilføje en kolonne til bar . Det er renere at modellere, og det betyder, at du laver mindre opdateringsbloat i bar , som kan sænke forespørgsler til bar .




  1. MySQL hvordan man får en sum af start/slutdatoer med mulige overlappende datoer

  2. Skal jeg åbne flere databaseforbindelser eller dele 1 i PHP/MySQL?

  3. PL/SQL-sammenligningsfejl i trigger (PLS-00405)

  4. Heltal vs char for DB record egenskab