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

Blokowanie predykatów w PostgreSQL 9.2.1 z izolacją Serializable

Z Izolowanie transakcji strona:

EXPLAIN na tym SELECT może powiedzieć, jaki plan zapytania jest brany, ale jeśli tabela jest mała (lub pusta!), PostgreSQL prawie na pewno wybierze skanowanie sekwencyjne zamiast odwoływać się do indeksu. Spowoduje to blokadę predykatu w całej tabeli, powodując niepowodzenie serializacji za każdym razem, gdy inna transakcja zrobi cokolwiek z tabelą.

W moim systemie:

isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on mydevice  (cost=0.00..23.38 rows=5 width=46)
   Filter: (cid = 1)
(2 rows)

Możesz spróbować dodać indeks i zmusić go do używania tego:

isolation=# CREATE INDEX mydevice_cid_key ON mydevice (cid);
CREATE INDEX
isolation=# SET enable_seqscan = off;
SET
isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                                    QUERY PLAN                                    
----------------------------------------------------------------------------------
 Index Scan using mydevice_cid_key on mydevice  (cost=0.00..8.27 rows=1 width=46)
   Index Cond: (cid = 1)
(2 rows)

Nie jest to jednak właściwe rozwiązanie. Cofnijmy się trochę.

Serializable ma na celu zagwarantowanie, że transakcje będą miały dokładnie taki sam efekt, jak gdyby były uruchamiane jedna po drugiej, pomimo faktu, że faktycznie uruchamiasz te transakcje jednocześnie. PostgreSQL nie ma nieskończonych zasobów, więc chociaż prawdą jest, że nakłada blokady predykatów na dane, do których faktycznie uzyskuje dostęp twoje zapytanie, „dane” mogą oznaczać więcej niż „zwrócone wiersze”.

PostgreSQL wybiera flagowanie niepowodzeń serializacji, gdy uważa, że ​​może wystąpić problem, a nie wtedy, gdy jest to pewne. (Stąd uogólnia blokady wierszy na blokady stron). Ten wybór projektu powoduje fałszywe alarmy, takie jak ten w przykładzie. Fałszywe alarmy są mniej niż idealne, jednak nie wpływa to na poprawność semantyki izolacji.

Komunikat o błędzie to:

ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

Ta wskazówka jest kluczowa. Twoja aplikacja musi wychwycić błędy serializacji i ponowić całą operację . Dzieje się tak zawsze, gdy SERIALIZABLE jest w grze - gwarantuje poprawność szeregową pomimo współbieżności, ale nie może tego zrobić bez pomocy Twojej aplikacji. Innymi słowy, jeśli faktycznie dokonujesz równoczesnych modyfikacji, jedynym sposobem, w jaki PostgreSQL może spełnić wymagania dotyczące izolacji, jest poproszenie aplikacji o serializację. Tak więc:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak pg_dump bazę danych RDS Postgres?

  2. Jak zmapować atrybut liczby całkowitej modelu na ciąg?

  3. Jak napisać funkcję w plpgsql, która porównuje datę ze znacznikiem czasu bez strefy czasowej?

  4. jak stworzyć tabelę z wartościami zsumowanymi według roku w postgresie

  5. Jak skonfigurować rozszerzenie Postgres?