ISOLATION LEVEL SERIALIZABLE锁定postgresql 9.6

时间:2017-01-06 09:48:58

标签: postgresql isolation-level 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()功能;

我需要在ISOLATION LEVEL SERIALIZABLE函数的SELECT + UPDATE上实现updatedata(),因为我不想要“丢失更新”...我想设置SERIALIZABLE隔离级别 public.updatedata function()

如果存在异常,则在updatedata()函数中;我希望它回滚到savepoint foo并再次通过循环重试select + update进程...

但我得error"control reached end of function without RETURN" ...我无法理解问题所在。

2 个答案:

答案 0 :(得分:0)

在您拥有的每项功能中

EXCEPTION WHEN others THEN
End

最后。如果发生任何异常,则会触发此代码。由于之后没有return语句,因此"control reached end of function without RETURN"错误会崩溃。

分析这些例外,您将确切知道发生了什么。或者甚至更好,只需删除这些行。毕竟EXCEPTION WHEN others是万恶之源。

编辑:经过一些搜索后,似乎无法更改函数内的隔离级别。毕竟调用函数是一个查询,并且必须在任何查询之前设置隔离级别。

答案 1 :(得分:0)

  

我想仅在public.updatedata function()中设置SERIALIZABLE隔离级别。

你做不到。隔离是一种事务级属性。

  

如果存在异常,则在updatedata()函数中;我希望它回滚到保存点foo

您可以使用 app.run([ "$rootScope", "$templateCache", function($rootScope, $templateCache) { $rootScope.$on("$routeChangeStart", function(event, next, current) { if (typeof (current) !== "undefined") { $templateCache.remove(current.templateUrl); //<-- CLEAN CACHE OF ANGULAR OF HTML TEMPLATE } }); } ]); 块。

但如果您使用serializabile隔离,这实际上不会起作用,因为某些序列化失败只能在提交时找到。