sql >> Databasteknik >  >> RDS >> PostgreSQL

Uppdatering av databasrader utan att låsa tabellen i PostgreSQL 9.2

MVCC

För det första, om "normala operationer" består av SELECT frågor, kommer MVCC-modellen att ta hand om det automatiskt. UPDATE blockerar inte SELECT och vice versa. SELECT ser bara engagerad data (eller vad som har gjorts i samma transaktion), så resultatet av den stora UPDATE förblir osynlig för andra transaktioner tills den är klar (begärd).

Prestanda / uppblåsthet

Om du har inga andra objekt som refererar till den tabellen,
och du har inga samtidiga skrivoperationer (som skulle gå förlorade!),
och du har råd med ett mycket kort exklusivt lås på bordet,
och du har såklart extra diskutrymme:
Du kan hålla låsningen till ett minimum genom att skapa en uppdaterad version av tabellen i bakgrunden. Se till att den har allt för att vara en drop-in-ersättare, släpp sedan originalet och byt namn på dupen.

CREATE TABLE tbl_new (LIKE tbl_org INCLUDING CONSTRAINTS);

INSERT INTO tbl_new 
SELECT col_a, col_b, array[col] aS col_c
FROM   tbl_org;

Jag använder CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS) , eftersom (citerar manualen här):

Noll-begränsningar kopieras alltid till den nya tabellen. CHECK begränsningar kommer endast att kopieras om INCLUDING CONSTRAINTS specificeras;andra typer av begränsningar kommer aldrig att kopieras.

Se till att det nya bordet är klart. Sedan:

DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;

Resulterar i ett mycket kort tidsfönster, där tabellen uteslutande är låst.

Det här handlar egentligen bara om prestanda. Det skapar ett nytt bord utan uppsvällning ganska snabbt. Om du har främmande nycklar eller vyer kan du fortfarande gå den vägen, men du måste förbereda ett skript för att släppa och återskapa dessa objekt, vilket kan skapa ytterligare exklusiva lås.

Samtidiga skrivningar

Med samtidiga skrivoperationer är egentligen allt du kan göra att dela upp din uppdatering i bitar. Du kan inte göra det i en enda transaktion, eftersom lås endast släpps i slutet av en transaktion.

Du kunde använd dblink , som kan starta oberoende transaktioner på en annan databas, inklusive sig själv. På så sätt kan du göra allt i en enda DO uttalande eller en plpgsql-funktion med en loop. Här är ett löst relaterat svar med mer information om dblink:

  • Släpp eller skapa databas från lagrad procedur i PostgreSQL

Ditt tillvägagångssätt med markörer

En markör inuti funktionen kommer inte att köpa dig något . Alla funktioner inkluderas automatiskt i en transaktion och alla lås släpps först i slutet av transaktionen. Även om du använde CLOSE cursor (vilket du inte gör) det skulle bara frigöra vissa resurser, men inte släpp förvärvade lås på bordet. Jag citerar manualen:

CLOSE stänger portalen under en öppen markör. Detta kan användas för att frigöra resurser tidigare än transaktionens slut, eller för att frigöra markörvariabeln för att öppnas igen.

Du skulle behöva köra separat transaktioner eller (ab)använd dblink som gör det åt dig.




  1. Få ID från en villkorlig INSERT

  2. USER-funktion i Oracle

  3. INITCAP() Funktion i Oracle

  4. Förstå index i MySQL:Del tre