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

Заключване на предикат в PostgreSQL 9.2.1 с изолация с възможност за сериализиране

От изолация на транзакция страница:

EXPLAIN върху този SELECT може да ви каже какъв е планът за заявка, но ако таблицата е малка (или празна!), PostgreSQL почти сигурно ще избере последователно сканиране, вместо да препраща към индекса. Това ще доведе до предикатно заключване на цялата таблица, причинявайки неуспешна сериализация, когато друга транзакция направи нещо с таблицата.

В моята система:

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)

Можете да опитате да добавите индекс и да го принудите да използва това:

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)

Това обаче не е правилното решение. Нека направим малко резервно копие.

Serializable има за цел да гарантира, че транзакциите ще имат точно същия ефект, както ако се изпълняват една след друга, въпреки факта, че всъщност изпълнявате тези транзакции едновременно. PostgreSQL няма безкрайни ресурси, така че макар да е вярно, че поставя предикатни ключалки на данни, до които вашата заявка действително има достъп, „данни“ може да означава повече от „върнати редове“.

PostgreSQL избира да маркира грешките на сериализацията, когато смята, че може да има проблем, а не когато е сигурно. (Оттук и как обобщава заключванията на редове към заключванията на страници.) ​​Този избор на дизайн води до фалшиви положителни резултати, като този във вашия пример. Фалшивите положителни резултати са по-малко от идеалните, но не влияят на коректността на семантиката на изолацията.

Съобщението за грешка е:

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.

Този намек е ключов. Вашето приложение трябва да улови неуспешни сериализации и опитайте отново цялата операция . Това е вярно винаги, когато SERIALIZABLE е в действие -- гарантира серийна коректност въпреки паралелността, но не може да направи това без помощта на вашето приложение. Казано по друг начин, ако всъщност правите едновременни модификации, единственият начин, по който PostgreSQL може да удовлетвори изискванията за изолация, е да помолите вашето приложение да се сериализира. Така:



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

  2. Запитване за персонализиран параметър postgresql с оператор SELECT

  3. Как работи Setseed() в PostgreSQL

  4. Как да съхранявате рамка от данни на pandas с обекти с данни тип datetime.timedelta в d/b на postgresql с помощта на sqlalchemy?

  5. Какво означават дробите TX и XID в инструмента pgadmin на postgres