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

Konzistence v postgresql se zamykáním a výběrem pro aktualizaci

BEGIN; 
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE; 
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;

Zdá se, že to funguje v Read Committed. Je pouze sql (stejný jako váš kód) a lze jej spustit v jednom volání (rychlejší).

@Seth Robertson:Bez LOCK TABLE a bez smyčky while to není bezpečné.

Pokud existuje transakce A a transakce B současně:A vybere první řádek a B vybere první řádek. A zamkne a aktualizuje řádek, B musí počkat, dokud A nepotvrdí. Potom B znovu zkontroluje podmínku job_name IS NULL. Je to nepravda a B se neaktualizuje - B nevybere další řádek, ale pouze znovu zkontroluje a vrátí prázdný výsledek.

@joegester:SELECT FOR UPDATE není problém, protože všechny tabulky jsou uzamčeny.

Možná existuje jiný způsob, jak to udělat - pokud místo toho smažete a vložíte řádky (do jiné tabulky?) a nastavíte NULL. Ale nejsem si jistý jak.



  1. MYSQL Přidejte pracovní dny k dnešnímu dni

  2. Psaní dotazu na dědičnost napsaného v SQL pomocí vnitřního spojení?

  3. Použití SUM na FLOAT datech

  4. zachytit výjimku DB v aplikaci JSF+EJB