sql >> Databasteknik >  >> RDS >> PostgreSQL

Undvika PostgreSQL dödlägen när du utför massuppdateringar och raderingsåtgärder

Använd explicit låsning på radnivå i ordnade underfrågor i alla konkurrerande frågor .
(SELECT konkurrerar inte med skrivlås.)

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;

På så sätt låses rader i konsekvent ordning enligt instruktionerna i manualen.

Förutsatt att id_A , id_B uppdateras aldrig, inte ens sällsynta hörnfallskomplikationer som beskrivs i rutan "Varning" i manualen är inte möjliga.

Utan att uppdatera nyckelkolumner kan du använda det svagare låsläget FOR NO KEY UPDATE . Kräver Postgres 9.3 eller senare.

Den andra (långsam och visst) alternativet är att använda Serialiserbar isoleringsnivå för konkurrerande transaktioner. Du måste förbereda dig för serialiseringsfel, i så fall måste du försöka kommandot igen.




  1. Hur ersätter man specifika värden i en Oracle-databaskolumn?

  2. Använder datum i en kontrollbegränsning, Oracle

  3. Databasbelastningsbalansering:distribuerade vs centraliserade inställningar

  4. Hur man ställer in varje objekt som hämtas från SQLite-databasen till en egen textvy