2017-01-06 1 views
0
CREATE OR REPLACE FUNCTION public.updatedata(userid_ integer) 
RETURNS integer 
AS $$ 
DECLARE 
userdata_ integer; 
BEGIN 

LOOP 
BEGIN 
    PERFORM 1 FROM public.footable f WHERE f.userid=userid_ LIMIT 1 FOR UPDATE ; 
    userdata_:=(SELECT f.userdata FROM public.footable f WHERE f.userid=userid_ ); 
    UPDATE public.footable f SET userdata = userdata_ + 1 WHERE f.userid=userid_ ; 
EXIT ; 
EXCEPTION WHEN others THEN 
END; 
END LOOP; 

RETURN userdata_ + 1; 
EXCEPTION WHEN others THEN 
END $$ language plpgsql; 

Kann ich verhindern "lost update" Problem für Benutzerdaten Spalte, wenn i "FOR UPDATE" wie diese Sperre benutzen?FOR UPDATE Lock postgresql 9,6

Eigentlich wollte ich serializable isolation in erster Linie verwenden, aber es stellt sich heraus, dass nur in serializable isolation können einige Fehler nach COMMIT nachgewiesen werden (link)

Antwort

0

Ihr Code wird ein verlorenes Update vermeiden, aber man kann das erreichen SQL-Anweisung gleiche mit einem einfachen:

UPDATE public.footable f 
SET userdata = userdata + 1 
WHERE f.userid = userid_ 
RETURNING userdata; 

Es kann kein verlorenes Update sein, weil die erste UPDATE wird die Zeile im exklusiven Modus sperren, und jede gleichzeitige UPDATE müssen warten, bis die Transaktion die Sperre hält, erfolgt, und dann die res ut der ersten UPDATE ist für die zweite sichtbar.

+0

toll .... danke .... – sommeguyy