sql >> Database teknologi >  >> RDS >> PostgreSQL

Undgå PostgreSQL-deadlocks, når du udfører masseopdateringer og sletningsoperationer

Brug eksplicit låsning på rækkeniveau i ordnede underforespørgsler i alle konkurrerende forespørgsler .
(VÆLG konkurrerer ikke med skrivelåse.)

SLET

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;

OPDATERING

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;

På denne måde låses rækker i ensartet rækkefølge som anbefalet i manualen.

Forudsat at id_A , id_B bliver aldrig opdateret, selv sjældne komplikationer i hjørnet, som beskrevet i boksen "Forsigtig" i manualen, er ikke mulige.

Mens du ikke opdaterer nøglekolonner, kan du bruge den svagere låsetilstand FOR INGEN NØGLEOPDATERING . Kræver Postgres 9.3 eller nyere.

Den anden (langsom og sikker) mulighed er at bruge det serialiserede isolationsniveau til konkurrerende transaktioner. Du skal forberede dig på serialiseringsfejl, i hvilket tilfælde du skal prøve kommandoen igen.




  1. Slet alle duplikerede rækker undtagen én i MySQL?

  2. Sådan undgår du at indsætte duplikerede poster i SQL INSERT-forespørgsel (5 nemme måder)

  3. Skift separatoren til et komma i SQLite-forespørgselsresultater

  4. Grupperet aggregeret pushdown