MVCC
Po pierwsze, jeśli "normalne operacje" składają się z SELECT
zapytań, model MVCC zajmie się tym automatycznie. UPDATE
nie blokuje SELECT
i wzajemnie. SELECT
widzi tylko zatwierdzone dane (lub to, co zostało zrobione w tej samej transakcji), więc wynik dużej UPDATE
pozostaje niewidoczny dla innych transakcji, dopóki nie zostanie wykonany (zatwierdzony).
Wydajność / wzdęcia
Jeśli nie masz innych obiektów odwołujących się do tej tabeli,
i nie masz jednoczesnych operacji zapisu (które zostałyby utracone!),
i możesz sobie pozwolić na bardzo krótką ekskluzywną blokadę na stole
i masz oczywiście dodatkowe miejsce na dysku:
Możesz ograniczyć blokowanie do minimum, tworząc zaktualizowaną wersję tabeli w tle. Upewnij się, że ma wszystko być zamiennikiem drop-in, a następnie usuń oryginał i zmień nazwę duplikatu.
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;
Używam CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS)
, ponieważ (cytując instrukcję tutaj):
Ograniczenia niepuste są zawsze kopiowane do nowej tabeli. CHECK
ograniczenia zostaną skopiowane tylko wtedy, gdy INCLUDING CONSTRAINTS
jest określony;inne typy ograniczeń nigdy nie zostaną skopiowane.
Upewnij się, że nowy stół jest gotowy. Następnie:
DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;
Powoduje to bardzo krótkie okno czasowe, w którym stół jest wyłącznie zablokowany.
Tak naprawdę chodzi tylko o wydajność. Dość szybko tworzy nowy stół bez żadnych wzdęć. Jeśli masz obce klucze lub widoki, nadal możesz iść tą drogą, ale musisz przygotować skrypt, aby usunąć i odtworzyć te obiekty, potencjalnie tworząc dodatkowe ekskluzywne blokady.
Równoczesne zapisy
Przy współbieżnych operacjach zapisu naprawdę wszystko, co możesz zrobić, to podzielić aktualizację na kawałki. Nie możesz tego zrobić w pojedynczej transakcji, ponieważ blokady są zwalniane dopiero po zakończeniu transakcji.
możesz zatrudnij dblink , który może uruchamiać niezależne transakcje na innej bazie danych, w tym na sobie. W ten sposób możesz zrobić to wszystko w jednym DO
instrukcja lub funkcja plpgsql z pętlą. Oto luźno powiązana odpowiedź z dodatkowymi informacjami na temat dblink:
- Upuść lub utwórz bazę danych z procedury składowanej w PostgreSQL
Twoje podejście z kursorami
Kursor wewnątrz funkcji nie kupi Ci niczego . Każda funkcja jest automatycznie włączana do transakcji, a wszystkie blokady są zwalniane dopiero na końcu transakcji. Nawet jeśli użyłeś CLOSE cursor
(czego nie robisz) zwolniłoby to tylko niektóre zasoby, ale nie zwolnić nabyte blokady na stole. Cytuję instrukcję:
CLOSE
zamyka portal pod otwartym kursorem. Można to wykorzystać do zwolnienia zasobów przed zakończeniem transakcji lub do zwolnienia zmiennej kursora do ponownego otwarcia.
Musisz uruchomić oddzielnie transakcje lub (ab)użyj dblink, który zrobi to za Ciebie.