sql >> Database >  >> RDS >> PostgreSQL

Databaserijen bijwerken zonder de tabel te vergrendelen in PostgreSQL 9.2

MVCC

Ten eerste, als "normale bewerkingen" bestaan ​​uit SELECT query's, zal het MVCC-model dit automatisch regelen. UPDATE blokkeert SELECT niet en vice versa. SELECT ziet alleen vastgelegde gegevens (of wat er in dezelfde transactie is gedaan), dus het resultaat van de grote UPDATE blijft onzichtbaar voor andere transacties totdat het is voltooid (toegezegd).

Prestatie / opgeblazen gevoel

Als je hebt geen andere objecten die naar die tabel verwijzen,
en je hebt geen gelijktijdige schrijfbewerkingen (die zouden verloren gaan!),
en je kunt je een heel kort exclusief slot op tafel veroorloven,
en je hebt natuurlijk de extra schijfruimte:
Je zou de vergrendeling tot een minimum kunnen beperken door een bijgewerkte versie van de tabel op de achtergrond te maken. Zorg ervoor dat het alles heeft om een ​​drop-in vervanging te zijn, laat dan het origineel vallen en hernoem de dupe.

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;

Ik gebruik CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS) , omdat (hier de handleiding geciteerd):

Niet-null-beperkingen worden altijd naar de nieuwe tabel gekopieerd. CHECK beperkingen worden alleen gekopieerd als INCLUDING CONSTRAINTS is gespecificeerd; andere soorten beperkingen zullen nooit worden gekopieerd.

Zorg ervoor dat de nieuwe tafel klaar is. Dan:

DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;

Resulteert in een zeer kort tijdvenster, waarbij de tafel exclusief is vergrendeld.

Dit gaat eigenlijk alleen over prestaties. Het creëert vrij snel een nieuwe tafel zonder enige bloat. Als je externe sleutels of views hebt, kun je nog steeds die route volgen, maar je moet een script voorbereiden om deze objecten te laten vallen en opnieuw te maken, waardoor mogelijk extra exclusieve sloten worden gemaakt.

Gelijktijdige schrijfacties

Met gelijktijdige schrijfbewerkingen is het enige dat u kunt doen, uw update in delen opsplitsen. Dat kan niet in een enkele transactie, aangezien sloten pas aan het einde van een transactie worden vrijgegeven.

Je zou gebruik dblink , die onafhankelijke transacties op een andere database kan starten, inclusief zichzelf. Op deze manier zou je het allemaal in een enkele DO . kunnen doen statement of een plpgsql-functie met een lus. Hier is een losjes gerelateerd antwoord met meer informatie over dblink:

  • Drop of creëer database van opgeslagen procedure in PostgreSQL

Uw benadering met cursors

Een cursor in de functie zal je niets kopen . Elke functie wordt automatisch in een transactie ingesloten en alle vergrendelingen worden pas vrijgegeven aan het einde van de transactie. Zelfs als u CLOSE cursor hebt gebruikt (wat je niet doet) het zou alleen wat middelen vrijmaken, maar niet ontgrendel de verworven sloten op de tafel. Ik citeer de handleiding:

CLOSE sluit de portal onder een open cursor. Dit kan worden gebruikt om bronnen eerder vrij te geven dan het einde van de transactie, of om de cursorvariabele vrij te maken om opnieuw te worden geopend.

U zou apart . moeten uitvoeren transacties of (ab)gebruik dblink die dat voor u doet.




  1. Huidige tijd in UTC gebruiken als standaardwaarde in PostgreSQL

  2. Wat is de beste manier om een ​​afbeelding van een SQL-serverdatabase in asp.net weer te geven?

  3. Hoe Atan() werkt in PostgreSQL

  4. Dump een mysql-database naar een back-up met leesbare tekst (CSV) vanaf de opdrachtregel