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

Atomic UPDATE .. SELECT в Postgres

Докато предложението на Ървин е може би най-простото начин да получите правилно поведение (стига да опитате отново транзакцията си, ако получите изключение с SQLSTATE от 40001), приложенията с опашка по своето естество са склонни да работят по-добре с блокиране на заявки за шанс да заемат своя ред на опашката, отколкото с реализацията на PostgreSQL на SERIALIZABLE транзакции, което позволява по-висока едновременност и е малко по-„оптимистично“ по отношение на шансовете за сблъсък.

Примерната заявка във въпроса, както е сега, в READ COMMITTED по подразбиране Нивото на изолация на транзакциите би позволило на две (или повече) едновременни връзки и двете да "заявят" един и същ ред от опашката. Какво ще се случи е следното:

  • T1 започва и стига до заключването на реда в UPDATE фаза.
  • T2 припокрива T1 във времето на изпълнение и се опитва да актуализира този ред. Той блокира в очакване на COMMIT или ROLLBACK на Т1.
  • T1 извършва ангажименти, след като успешно „заявява“ реда.
  • T2 се опитва да актуализира реда, открива, че T1 вече има, търси новата версия на реда, открива, че все още отговаря на критериите за избор (който е точно този id съвпада), а също и "заявява" реда.

Може да бъде модифициран, за да работи правилно (ако използвате версия на PostgreSQL, която позволява FOR UPDATE клауза в подзаявка). Просто добавете FOR UPDATE до края на подзаявката, която избира идентификатора и това ще се случи:

  • T1 стартира и сега заключва реда преди избиране идентификационният номер.
  • T2 припокрива T1 във времето за изпълнение и блокира, докато се опитва да избере идентификатор, в очакване на COMMIT или ROLLBACK на Т1.
  • T1 извършва ангажименти, след като успешно „заявява“ реда.
  • До момента, в който T2 е в състояние да чете реда, за да види идентификатора, той вижда, че е заявен, така че намира следващия наличен идентификатор.

В REPEATABLE READ или SERIALIZABLE ниво на изолация на транзакциите, конфликтът при запис ще доведе до грешка, която бихте могли да хванете и да определите, че е неуспешна сериализация въз основа на SQLSTATE, и да опитате отново.

Ако обикновено искате СЕРИАЛИЗИРУЕМИ транзакции, но искате да избегнете повторни опити в зоната на опашката, може да успеете да постигнете това, като използвате заключване за съвет.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails:FATAL - Удостоверяването на партньора не бе успешно за потребител (PG::Error)

  2. Как да излезете от помощната програма за командния ред на PostgreSQLs (psql)

  3. Присъединете четири таблици, включващи LEFT JOIN без дубликати

  4. Може ли PostgreSQL да има ограничение за уникалност върху елементите на масива?

  5. Изпълнение на последователности и сериали в Postgres-XL