sql >> Databáze >  >> RDS >> PostgreSQL

Predikátové zamykání v PostgreSQL 9.2.1 se serializovatelnou izolací

Z izolace transakcí stránka:

EXPLAIN na tom SELECT může vám sdělit, jaký plán dotazů se bere, ale pokud je tabulka malá (nebo prázdná!), PostgreSQL téměř jistě vybere sekvenční skenování namísto odkazování na index. To způsobí predikátový zámek na celé tabulce, což způsobí selhání serializace, kdykoli s tabulkou něco udělá jiná transakce.

V mém systému:

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)

Můžete zkusit přidat index a přinutit jej, aby to použil:

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)

To však není správné řešení. Pojďme trochu zálohovat.

Serializable má zaručit, že transakce budou mít přesně stejný efekt, jako kdyby byly spouštěny jedna po druhé, a to navzdory skutečnosti, že tyto transakce ve skutečnosti spouštíte souběžně. PostgreSQL nemá nekonečné zdroje, takže i když je pravda, že vkládá predikátové zámky na data, ke kterým váš dotaz skutečně přistupuje, „data“ může znamenat více než „vrácené řádky“.

PostgreSQL se rozhodne označovat selhání serializace, když si myslí, že by mohl nastat problém, ne když si je jistý. (Proto zobecňuje zámky řádků na zámky stránek.) Tato volba návrhu způsobí falešně pozitivní výsledky, jako je ta ve vašem příkladu. Falešné poplachy jsou méně než ideální, ale neovlivňují správnost sémantiky izolace.

Chybová zpráva je:

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 nápověda je klíčová. Vaše aplikace musí zachytit selhání serializace a zkusit celou operaci znovu . To platí vždy, když je SERIALIZABLE je ve hře -- zaručuje sériovou správnost navzdory souběžnosti, ale bez pomoci vaší aplikace to nedokáže. Jinými slovy, pokud ve skutečnosti provádíte souběžné úpravy, jediný způsob, jak může PostgreSQL splnit požadavky na izolaci, je požádat vaši aplikaci, aby se sama serializovala. Tedy:



  1. Co děláte na SQL Serveru pro VYTVOŘENÍ NEBO ZMĚNU?

  2. Průběžný součet přes opakující se skupiny podle položek na základě času v Oracle SQL

  3. PostgreSQL parametrizované Order By / Limit v tabulkové funkci

  4. Asynchronní DBAppender s logbackem