sql >> Databasteknik >  >> RDS >> PostgreSQL

Atomic UPDATE .. SELECT i Postgres

Medan Erwins förslag möjligen är det enklaste sätt att få korrekt beteende (så länge du försöker om din transaktion om du får ett undantag med SQLSTATE av 40001), tenderar köapplikationer till sin natur att fungera bättre med förfrågningar som blockerar för en chans att ta sin tur i kön än med PostgreSQL-implementeringen av SERIALIZABLE transaktioner, vilket tillåter högre samtidighet och är något mer "optimistisk" om riskerna för kollision.

Exempelfrågan i frågan, som den står, i standardvärdet READ COMMITTED transaktionsisoleringsnivån skulle tillåta två (eller flera) samtidiga anslutningar att båda "anspråka" samma rad från kön. Vad som kommer att hända är detta:

  • T1 startar och når så långt som att låsa raden i UPDATE fas.
  • T2 överlappar T1 i körningstid och försöker uppdatera den raden. Den blockerar i väntan på COMMIT eller ROLLBACK av T1.
  • T1 begår, efter att ha "gjort anspråk på" raden.
  • T2 försöker uppdatera raden, upptäcker att T1 redan har, letar efter den nya versionen av raden, upptäcker att den fortfarande uppfyller urvalskriterierna (vilket är just det id matchar), och "gör anspråk" på raden.

Den kan modifieras för att fungera korrekt (om du använder en version av PostgreSQL som tillåter FOR UPDATE klausul i en underfråga). Lägg bara till FOR UPDATE till slutet av underfrågan som väljer id, och detta kommer att hända:

  • T1 startar och låser nu raden innan du väljer id.
  • T2 överlappar T1 i exekveringstid och blockerar när man försöker välja ett id, i väntan på COMMIT eller ROLLBACK av T1.
  • T1 begår, efter att ha "gjort anspråk på" raden.
  • När T2 kan läsa raden för att se id:t ser den att det har gjorts anspråk på det, så det hittar nästa tillgängliga id.

Vid REPEATABLE READ eller SERIALIZABLE transaktionsisoleringsnivå, skulle skrivkonflikten skapa ett fel, som du kunde fånga och fastställa var ett serialiseringsfel baserat på SQLSTATE, och försök igen.

Om du i allmänhet vill ha SERIALISERBARA transaktioner men du vill undvika omförsök i köområdet, kanske du kan åstadkomma det genom att använda ett rådgivande lås.



  1. Hur man importerar en databas med phpMyAdmin

  2. Hur man konverterar versaler till gemener i SQL Server – LOWER()

  3. JDBC Skapa tabell Exempel Användningsförklaring

  4. 5 tecken på att du har vuxit ur Excel