sql >> Database >  >> RDS >> PostgreSQL

Vergrendel en transactie in postgre die een zoekopdracht zou moeten blokkeren

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 .



  1. Is het mogelijk om een ​​schending van een buitenlandse sleutel in postgres op te vangen?

  2. Voorwaardelijke hulp bij SQL-query's

  3. Inleiding tot Multi-Statement Table-Valued Functions (MSTVF) in SQL Server

  4. Sorteer resultaten zodat ze overeenkomen met de volgorde van waarden in een WHERE IN-expressie