PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Актуализиране на редовете на базата данни без заключване на таблицата в PostgreSQL 9.2

MVCC

Първо, ако "нормалните операции" се състоят от SELECT заявки, моделът MVCC ще се погрижи за това автоматично. UPDATE не блокира SELECT и обратно. SELECT вижда само ангажирани данни (или това, което е направено в същата транзакция), така че резултатът от голямото UPDATE остава невидим за други транзакции, докато не бъде направен (ангажиран).

Изпълнение/раздуване

Ако нямате други обекти, препращащи към тази таблица,
и нямате едновременни операции за запис (които биха били загубени!),
и можете да си позволите много къса изключителна ключалка на масата,
и имате допълнително дисково пространство, разбира се:
Можете да намалите заключването до минимум, като създадете актуализирана версия на таблицата във фонов режим. Уверете се, че има всичко за да бъде заместник, след което изхвърлете оригинала и преименувайте фалшивото.

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;

Използвам CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS) , защото (цитирайки ръководството тук):

Ненулевите ограничения винаги се копират в новата таблица. CHECK ограниченията ще бъдат копирани само ако INCLUDING CONSTRAINTS е посочено; други типове ограничения никога няма да бъдат копирани.

Уверете се, че новата маса е готова. След това:

DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;

Резултатът е много кратък период от време, при който таблицата е изключително заключена.

Това всъщност е само за производителност. Създава нова маса без никакво раздуване доста бързо. Ако имате външни ключове или изгледи, все още можете да вървите по този път, но трябва да подготвите скрипт за пускане и пресъздаване на тези обекти, което потенциално създава допълнителни изключителни ключалки.

Едновременно записвания

С едновременни операции по запис, наистина всичко, което можете да направите, е да разделите актуализацията си на парчета. Не можете да направите това в една транзакция, тъй като заключванията се освобождават само в края на транзакция.

Вие можете използвайте dblink , който може да стартира независими транзакции в друга база данни, включително самата нея. По този начин можете да направите всичко с едно DO оператор или функция plpgsql с цикъл. Ето един слабо свързан отговор с повече информация за dblink:

  • Изхвърлете или създайте база данни от съхранената процедура в PostgreSQL

Вашият подход с курсори

Курсорът във функцията няма да ви купи нищо . Всяка функция се включва автоматично в транзакция и всички заключвания се освобождават само в края на транзакцията. Дори ако сте използвали CLOSE cursor (което не правите) това би освободило само някои ресурси, но не освободете придобитите ключалки на масата. Цитирам ръководството:

CLOSE затваря портала под отворен курсор. Това може да се използва за освобождаване на ресурси по-рано от края на транзакцията или за освобождаване на променливата на курсора, за да бъде отворена отново.

Ще трябва да стартирате отделно транзакциите или (зло)използвайте dblink, който прави това вместо вас.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получа локални данни в база данни само за четене с помощта на dplyr?

  2. Делението на цели числа връща 0

  3. Как да зададете изчакване на връзката в SQLAlchemy

  4. NOT IN в postgresql не работи

  5. Потребители на приложението срещу защита на ниво ред