PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Atomic UPDATE .. SELECT w Postgres

Chociaż sugestia Erwina jest prawdopodobnie najprostsza sposób na uzyskanie poprawnego zachowania (o ile ponawiasz transakcję, jeśli otrzymasz wyjątek z SQLSTATE 40001), aplikacje kolejkujące z natury działają lepiej z blokowaniem żądań, aby mieć szansę na zmianę w kolejce, niż z implementacją SERIALIZABLE w PostgreSQL transakcji, co pozwala na wyższą współbieżność i jest nieco bardziej „optymistyczne” co do prawdopodobieństwa kolizji.

Przykładowe zapytanie w pytaniu, w obecnej formie, w domyślnym READ COMMITTED poziom izolacji transakcji umożliwiłby dwóm (lub więcej) równoczesnym połączeniom zarówno „odebranie” tego samego wiersza z kolejki. Co się stanie, to:

  • T1 uruchamia się i dochodzi do zablokowania wiersza w UPDATE faza.
  • T2 nakłada się na T1 w czasie wykonywania i próbuje zaktualizować ten wiersz. Blokuje oczekujące na COMMIT lub ROLLBACK z T1.
  • T1 zatwierdza, po pomyślnym „zajęciu” wiersza.
  • T2 próbuje zaktualizować wiersz, stwierdza, że ​​T1 już ma, szuka nowej wersji wiersza, stwierdza, że ​​nadal spełnia kryteria wyboru (czyli po prostu ten id dopasowania), a także „zajmuje” wiersz.

Można go zmodyfikować, aby działał poprawnie (jeśli używasz wersji PostgreSQL, która umożliwia FOR UPDATE klauzula w podzapytaniu). Po prostu dodaj FOR UPDATE do końca podzapytania, które wybiera identyfikator, a stanie się to:

  • T1 uruchamia się i blokuje teraz wiersz przed wybraniem identyfikator.
  • T2 nakłada się na T1 w czasie wykonania i blokuje podczas próby wybrania identyfikatora, w oczekiwaniu na COMMIT lub ROLLBACK z T1.
  • T1 zatwierdza, po pomyślnym „zajęciu” wiersza.
  • Zanim T2 będzie w stanie czytać wiersz, aby zobaczyć identyfikator, widzi, że został zgłoszony, więc znajduje następny dostępny identyfikator.

W REPEATABLE READ lub SERIALIZABLE na poziomie izolacji transakcji, konflikt zapisu spowodowałby błąd, który można wykryć i określić jako błąd serializacji w oparciu o stan SQLSTATE, i spróbować ponownie.

Jeśli generalnie chcesz SERIALIZOWAĆ transakcje, ale chcesz uniknąć ponownych prób w obszarze kolejkowania, możesz to osiągnąć za pomocą blokady doradczej.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. UPDATE za pomocą ORDER BY

  2. Jak zwrócić tylko czas pracy z rezerwacji w PostgreSql?

  3. INSERT z dynamiczną nazwą tabeli w funkcji wyzwalacza

  4. Nazwa dynamicznej tabeli zapytań SQL w FOR

  5. Postgres nie używa indeksu, gdy skanowanie indeksu jest znacznie lepszą opcją