2017-01-06 6 views
0
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() функция;УРОВЕНЬ ИЗОЛЯЦИИ SERIALIZABLE lock postgresql 9.6

Мне нужно реализовать ISOLATION LEVEL SERIALIZABLE на SELECT + UPDATE в updatedata() функции, потому что я не хочу «потерянное обновление» ... Я хочу, чтобы установить уровень изоляции SERIALIZABLE в public.updatedata function() только.

И в updatedata() функция, если есть исключение; я хочу, чтобы откатить к savepoint foo и повторите select + update процесс через петлю снова ...

Но я получаю error говоря "control reached end of function without RETURN" ... Я не могу понять, где проблема.

ответ

0

Я хочу установить SERIALIZABLE уровень изоляции только в public.updatedata function().

Вы не можете. Изоляция - свойство уровня транзакции.

И в функции updatedata(), если есть исключение; я хочу, чтобы он откат до savepoint foo

Для этого вы можете использовать блок BEGIN ... EXCEPTION ....

Но это не будет работать, если вы используете сериализованную изоляцию, поскольку некоторые сбои сериализации могут быть найдены только в момент фиксации.

+0

.... «Но это на самом деле не работает, если вы используете сериализованную изоляцию, поскольку некоторые сбои сериализации могут быть найдены только в момент фиксации». ..... Нет другого способа сделать это? Я имею в виду работу вокруг? – sommeguyy

+0

@sommeguyy Вы не ясно объяснили основную проблему, которую пытаетесь решить, поэтому трудно сказать. –

+0

В итоге я решил свою проблему, используя блокировку «FOR UPDATE». – sommeguyy

0

В каждой функции у вас есть

EXCEPTION WHEN others THEN 
End 

в конце. Если происходит какое-либо исключение, то этот кусок кода срабатывает. И поскольку после этого нет инструкции return, она вылетает с ошибкой "control reached end of function without RETURN".

Анализ этих исключений, и вы точно будете знать, что происходит. Или даже лучше, просто удалите эти строки. Ведь EXCEPTION WHEN others является корнем всего зла.


EDIT: После некоторого поиска, кажется, что вы не можете изменить уровень изоляции внутри функции. После вызова функции необходимо задать уровень запроса и изоляции перед любым запросом.

+0

Если я удаляю его, как вы сказали, тогда он дает сообщение об ошибке «УСТАНОВИТЬ УРОВЕНЬ ИЗОБРАЖЕНИЯ СТАВКИ» перед любым запросом « – sommeguyy

+0

@sommeguyy Здесь вы идете. У вас есть «УСТАНОВИТЬ УРОВЕНЬ ИЗОБРАЖЕНИЯ ИЗОЛЯЦИИ, СЕРИЙНЫЙ», внутри цикла. Я предполагаю, что если вы перемещаете его снаружи (то есть 1 линия вверх), то это должно быть хорошо. – freakish

+0

К сожалению, я получаю такую ​​же ошибку ... – sommeguyy

Смежные вопросы