用于更新锁定 postgresql 9.6
FOR UPDATE lock postgresql 9.6
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;
当我像这样使用 "FOR UPDATE"
锁时,我可以防止用户数据列出现 "lost update"
问题吗?
其实我一开始想用serializable isolation
,结果发现serializable isolation
有些错误只能在commıt()
您的代码将避免丢失更新,但您可以通过简单的 SQL 语句实现相同的目的:
UPDATE public.footable f
SET userdata = userdata + 1
WHERE f.userid = userid_
RETURNING userdata;
不会有丢失的更新,因为第一个UPDATE
会以独占模式锁定该行,任何并发的UPDATE
都必须等到持有锁的事务完成,并且那么第一个 UPDATE
的结果对第二个可见。
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;
当我像这样使用 "FOR UPDATE"
锁时,我可以防止用户数据列出现 "lost update"
问题吗?
其实我一开始想用serializable isolation
,结果发现serializable isolation
有些错误只能在commıt(
您的代码将避免丢失更新,但您可以通过简单的 SQL 语句实现相同的目的:
UPDATE public.footable f
SET userdata = userdata + 1
WHERE f.userid = userid_
RETURNING userdata;
不会有丢失的更新,因为第一个UPDATE
会以独占模式锁定该行,任何并发的UPDATE
都必须等到持有锁的事务完成,并且那么第一个 UPDATE
的结果对第二个可见。