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;

当我像这样使用锁定时,我可以防止"lost update"用户数据列出现问题吗?"FOR UPDATE"

实际上我想首先使用serializable isolation,但事实证明,在serializable isolation某些错误中只能在 commıt( link ) 之后检测到

4

1 回答 1

0

您的代码将避免丢失更新,但您可以使用简单的 SQL 语句实现相同的目的:

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

不会丢失更新,因为第一个UPDATE将以独占模式锁定行,任何并发UPDATE都必须等到持有锁的事务完成,然后第一个的结果对UPDATE第二个可见。

于 2017-01-09T13:09:25.090 回答