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

Vyhněte se zablokování PostgreSQL při provádění operací hromadné aktualizace a mazání

Použijte explicitní uzamykání na úrovni řádků v uspořádaných poddotazech ve všech konkurenčních dotazech .
(SELECT nesoutěží se zámky zápisu.)

DELETE

DELETE FROM table_name t
USING (
   SELECT id_A, id_B
   FROM   table_name 
   WHERE  id_A = ANY(array_of_id_A)
   AND    id_B = ANY(array_of_id_B)
   ORDER  BY id_A, id_B
   FOR    UPDATE
   ) del
WHERE  t.id_A = del.id_A
AND    t.id_B = del.id_B;

UPDATE

UPDATE table_name t
SET    val_1 = 'some value'
     , val_2 = 'some value'
FROM  (
   SELECT id_A, id_B
   FROM   table_name 
   WHERE  id_A = ANY(array_of_id_A)
   AND    id_B = ANY(array_of_id_B)
   ORDER  BY id_A, id_B
   FOR    NO KEY UPDATE  -- Postgres 9.3+
-- FOR    UPDATE         -- for older versions or updates on key columns
   ) upd
WHERE  t.id_A = upd.id_A
AND    t.id_B = upd.id_B;

Tímto způsobem jsou řádky uzamčeny v konzistentním pořadí, jak je doporučeno v příručce.

Za předpokladu, že id_A , id_B se nikdy neaktualizují, dokonce ani vzácné komplikace rohového pouzdra, jak je popsáno v rámečku "Pozor" v příručce, nejsou možné.

I když neaktualizujete klíčové sloupce, můžete použít slabší režim uzamčení FOR NO KEY UPDATE . Vyžaduje Postgres 9.3 nebo novější.

Druhý (pomalý a jistá) možností je použít pro konkurenční transakce Serializable Isolation Level. Budete se muset připravit na selhání serializace, v takovém případě musíte příkaz zopakovat.




  1. Přestaňte prosím používat tento anti-vzor UPSERT

  2. provádění operací souvisejících s datem v PHP

  3. PDO + MySQL a nefunkční kódování UTF-8

  4. Mohu ukládat obrázky v MySQL