Het gedrag dat u beschrijft is normaal en wordt verwacht in elke relationele relationele database.
Als PostgreSQL u de waarde edited
liet zien voor de eerste SELECT
het zou verkeerd zijn om dat te doen - dat heet een "dirty read" en is slecht nieuws in databases.
PostgreSQL zou mogen wachten op de SELECT
totdat je commit of teruggedraaid hebt, maar het is niet vereist door de SQL-standaard, je hebt het niet verteld dat je wilt wachten, en het hoeft niet te wachten om een technische reden, dus het retourneert de gegevens die je hebt gevraagd voor onmiddellijk. Immers, totdat het is vastgelegd, die update
er bestaat maar een soort van - het kan nog steeds gebeuren of niet.
Als PostgreSQL hier altijd wachtte, zou je snel in een situatie terechtkomen waarin slechts één verbinding tegelijkertijd iets met de database zou kunnen doen. Niet mooi voor de prestaties, en het grootste deel van de tijd totaal onnodig.
Als u wilt wachten op een gelijktijdige UPDATE
(of DELETE
), gebruikt u SELECT ... FOR SHARE
. (Maar houd er rekening mee dat dit niet werkt voor INSERT
).
Details:
SELECT
zonder een FOR UPDATE
of FOR SHARE
clausule neemt geen vergrendelingen op rijniveau. Het ziet dus wat de huidige vastgelegde rij is en wordt niet beïnvloed door transacties tijdens de vlucht die die rij mogelijk wijzigen. De concepten worden uitgelegd in het MVCC-gedeelte van de documenten
. Het algemene idee is dat PostgreSQL copy-on-write is, met versiebeheer waarmee het de juiste kopie kan retourneren op basis van wat de transactie of het statement kon "zien" op het moment dat het begon - wat PostgreSQL een "snapshot" noemt.
In de standaard READ COMMITTED
isolatie-snapshots worden genomen op instructieniveau, dus als u SELECT
een rij, COMMIT
een wijziging van een andere transactie, en SELECT
nogmaals, je zult verschillende waarden zien, zelfs binnen één transatie. U kunt SNAPSHOT
. gebruiken isolatie als u geen wijzigingen wilt zien die zijn doorgevoerd nadat de transactie is begonnen, of SERIALIZABLE
isolatie om verdere bescherming toe te voegen tegen bepaalde soorten onderlinge afhankelijkheden van transacties.
Zie het hoofdstuk over transactie-isolatie in de documentatie .
Als je een SELECT
. wilt om te wachten op lopende transacties om wijzigingen in geselecteerde rijen vast te leggen of terug te draaien, moet u SELECT ... FOR SHARE
gebruiken . Dit blokkeert het slot dat is ingenomen door een UPDATE
of DELETE
totdat de transactie die de vergrendeling heeft veroorzaakt, wordt teruggedraaid of wordt vastgelegd.
INSERT
is echter anders - de tuples bestaan gewoon niet voor andere transacties totdat ze zijn vastgelegd. De enige manier om te wachten op gelijktijdige INSERT
s is om een EXCLUSIVE
. te nemen slot op tafelniveau, zodat u weet dat niemand anders van tafel verandert terwijl u deze leest. Meestal betekent de noodzaak om dat te doen dat u een ontwerpprobleem heeft in de toepassing - uw app zou niet zorgen moeten geven als er niet-vastgelegde insert
. zijn is nog in vlucht.
Zie het hoofdstuk over expliciete vergrendeling van de documentatie .