隔离级别可序列化锁定 postgresql 9.6
ISOLATION LEVEL SERIALIZABLE locking postgresql 9.6
DO $$
BEGIN
raise notice '%', (SELECT * from public.clientcalledthisfunction(1,2));
END $$;
CREATE OR REPLACE FUNCTION public.clientcalledthisfunction(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
result integer;
BEGIN
result:=(SELECT * from public.call_updatedata(userid1_, userid2_)) ;
RETURN result;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.call_updatedata(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
userdata_1 integer;
userdata_2 integer;
userdata_total integer;
BEGIN
SELECT * FROM public.updatedata(userid1_) INTO userdata_1;
SELECT * FROM public.updatedata(userid2_) INTO userdata_2;
userdata_total:=(userdata_1 + userdata_2);
RETURN userdata_total;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.updatedata(userid_ integer)
RETURNS integer
AS $$
DECLARE
userdata_ integer;
BEGIN
LOOP
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN
SAVEPOINT foo;
SELECT userdata FROM public.footable WHERE userid=userid_ INTO userdata_;
UPDATE public.footable SET userdata = userdata_ + 1 WHERE userid=userid_ ;
EXIT ;
EXCEPTION WHEN others THEN
ROLLBACK TO SAVEPOINT foo;
END;
END LOOP;
RETURN userdata_ + 1;
EXCEPTION WHEN others THEN
END $$ language plpgsql;
客户端calls public.clientcalledthisfunction()
函数;
我需要在 updatedata()
函数的 SELECT + UPDATE
上实现 ISOLATION LEVEL SERIALIZABLE
,因为我不想 "lost update"...我想设置 SERIALIZABLE 隔离级别 只有 public.updatedata function()
。
而在updatedata()
函数中如果有异常;我希望它回滚到 savepoint foo
并重试 select + update
再次循环处理...
但是我 error
说 "control reached end of function without RETURN"
...我不明白问题出在哪里。
在每个函数中你都有
EXCEPTION WHEN others THEN
End
最后。如果发生任何异常,则会触发这段代码。由于之后没有 return
语句,它会因 "control reached end of function without RETURN"
错误而崩溃。
分析那些异常,你就知道到底是怎么回事了。或者甚至更好,只需删除这些行。毕竟EXCEPTION WHEN others
是万恶之源
编辑: 经过一番搜索,您似乎无法在函数内更改隔离级别。毕竟调用函数是一个查询,必须在任何查询之前设置隔离级别。
I want to set SERIALIZABLE isolation level only in public.updatedata function().
你不能。隔离是事务级的 属性.
And in updatedata() function if there is an exception; i want it to rollback to savepoint foo
您可以为此使用 BEGIN ... EXCEPTION ...
块。
但如果您使用可序列化隔离,这实际上不会起作用,因为某些序列化失败只能在提交时发现。
DO $$
BEGIN
raise notice '%', (SELECT * from public.clientcalledthisfunction(1,2));
END $$;
CREATE OR REPLACE FUNCTION public.clientcalledthisfunction(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
result integer;
BEGIN
result:=(SELECT * from public.call_updatedata(userid1_, userid2_)) ;
RETURN result;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.call_updatedata(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
userdata_1 integer;
userdata_2 integer;
userdata_total integer;
BEGIN
SELECT * FROM public.updatedata(userid1_) INTO userdata_1;
SELECT * FROM public.updatedata(userid2_) INTO userdata_2;
userdata_total:=(userdata_1 + userdata_2);
RETURN userdata_total;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.updatedata(userid_ integer)
RETURNS integer
AS $$
DECLARE
userdata_ integer;
BEGIN
LOOP
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN
SAVEPOINT foo;
SELECT userdata FROM public.footable WHERE userid=userid_ INTO userdata_;
UPDATE public.footable SET userdata = userdata_ + 1 WHERE userid=userid_ ;
EXIT ;
EXCEPTION WHEN others THEN
ROLLBACK TO SAVEPOINT foo;
END;
END LOOP;
RETURN userdata_ + 1;
EXCEPTION WHEN others THEN
END $$ language plpgsql;
客户端calls public.clientcalledthisfunction()
函数;
我需要在 updatedata()
函数的 SELECT + UPDATE
上实现 ISOLATION LEVEL SERIALIZABLE
,因为我不想 "lost update"...我想设置 SERIALIZABLE 隔离级别 只有 public.updatedata function()
。
而在updatedata()
函数中如果有异常;我希望它回滚到 savepoint foo
并重试 select + update
再次循环处理...
但是我 error
说 "control reached end of function without RETURN"
...我不明白问题出在哪里。
在每个函数中你都有
EXCEPTION WHEN others THEN
End
最后。如果发生任何异常,则会触发这段代码。由于之后没有 return
语句,它会因 "control reached end of function without RETURN"
错误而崩溃。
分析那些异常,你就知道到底是怎么回事了。或者甚至更好,只需删除这些行。毕竟EXCEPTION WHEN others
是万恶之源
编辑: 经过一番搜索,您似乎无法在函数内更改隔离级别。毕竟调用函数是一个查询,必须在任何查询之前设置隔离级别。
I want to set SERIALIZABLE isolation level only in public.updatedata function().
你不能。隔离是事务级的 属性.
And in updatedata() function if there is an exception; i want it to rollback to savepoint foo
您可以为此使用 BEGIN ... EXCEPTION ...
块。
但如果您使用可序列化隔离,这实际上不会起作用,因为某些序列化失败只能在提交时发现。