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

Заключване и транзакция в postgres, които трябва да блокират заявка

Поведението, което описвате, е нормално и се очаква във всяка транзакционна релационна база данни.

Ако PostgreSQL ви е показал стойността edited за първия SELECT би било погрешно да го направите - това се нарича "мръсно четене" и е лоша новина в базите данни.

PostgreSQL ще има право да чака при SELECT докато не извършите ангажимент или върнете назад, но това не се изисква от SQL стандарта, не сте му казали, че искате да изчакате, и не трябва да чака поради някаква техническа причина, така че връща данните, които сте поискали за веднага. В края на краищата, докато не бъде ангажирано, тази update съществува само един вид - все още може или не може да се случи.

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

Ако искате да изчакате едновременна UPDATE (или DELETE ), ще използвате SELECT ... FOR SHARE . (Но имайте предвид, че това няма да работи за INSERT ).

Подробности:

SELECT без FOR UPDATE или FOR SHARE клаузата не приема никакво заключване на ниво ред. Така че той вижда какъвто и да е текущият ангажиран ред и не се влияе от транзакции по време на полет, които може да променят този ред. Концепциите са обяснени в раздела MVCC на документите . Общата идея е, че PostgreSQL е копиране при запис, с управление на версиите, което му позволява да върне правилното копие въз основа на това, което транзакцията или изявлението може да "види" в момента, в който е стартирано - това, което PostgreSQL нарича "моментна снимка".

В READ COMMITTED моментните снимки на изолацията се правят на ниво оператор, така че ако SELECT ред, COMMIT промяна в него от друга транзакция и SELECT отново ще видите различни стойности дори в рамките на една трансация. Можете да използвате SNAPSHOT изолация, ако не искате да видите извършени промени след началото на транзакцията, или SERIALIZABLE изолация за добавяне на допълнителна защита срещу определени видове взаимозависимости на транзакции.

Вижте главата за изолиране на транзакция в документацията .

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

INSERT е различен обаче - кортежите просто не съществуват за други транзакции, докато не се ангажират. Единственият начин да изчакате едновременно INSERT s е да вземете EXCLUSIVE заключване на ниво таблица, така че да знаете, че никой друг не променя таблицата, докато я четете. Обикновено необходимостта да направите това обаче означава, че имате проблем с дизайна в приложението - приложението ви не би трябвало да се интересува ако има незаети insert все още е в полет.

Вижте главата за изрично заключване в документацията .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как мога да вмъкна коментари на колони в PostgreSQL чрез Python?

  2. Експортирайте и импортирайте дъмп на таблица (.sql) с помощта на pgAdmin

  3. PostgreSQL - клауза GROUP BY

  4. Не може да се експортира таблица на AWS RDS Postgres в CSV в S3, като се използва функцията aws_s3.query_export_to_s3

  5. Мога ли да съкращавам таблици динамично?