установить уровень изоляции для хранимых процедур postgresql

Надеюсь, это простой вопрос, но один для чего я h не нашел достойного ответа. Мне достоверно известно, что хранимые процедуры (определяемые пользователем функции БД) в PostgreSQL (в частности, версия 9.0.4) по своей сути транзакционные, поскольку они вызываются с помощью оператора SELECT, который сам по себе является транзакцией. Итак, как выбрать уровень изоляции хранимой процедуры?Я полагаю, что в других СУБД желаемый транзакционный блок будет заключен в блок START TRANSACTION, для которого желаемый уровень изоляции является необязательным параметром.

В качестве конкретного выдуманного примера скажем, что я хочу сделать это:

CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS 
$$
BEGIN
        INSERT INTO data_table VALUES (rowtext);
        UPDATE row_counts_table SET count=count+1;
END;
$$  
LANGUAGE plpgsql
SECURITY DEFINER;

И представьте, что я хочу убедиться, что эта функция всегда выполняется как сериализуемая транзакция (да, да, PostgreSQL SERIALIZABLE не является должным образом сериализуемым, но дело не в этом). Я не хочу требовать, чтобы она вызывалась как

START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT add_new_row('foo');
COMMIT;

. Итак, как мне снизить требуемый уровень изоляции в функции? Я считаю, что я не могу просто указать уровень изоляции в операторе BEGIN , как в руководстве

Важно не путать использование of BEGIN / END для группировки операторов в PL / pgSQL с одноименным Команды SQL для управления транзакциями. BEGIN / END PL / pgSQL предназначены только для группировка; они не начинают и не заканчивают сделка. Функции и триггер процедуры всегда выполняются в сделка, установленная внешним запрос - они не могут начать или зафиксировать эта транзакция, так как будет нет контекста для их выполнения.

Наиболее очевидным подходом для меня было бы использование SET TRANSACTION где-нибудь в определении функции, например:

CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS 
$$
BEGIN
        SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
        INSERT INTO data_table VALUES (rowtext);
        UPDATE row_counts_table SET count=count+1;
END;
$$  
LANGUAGE plpgsql
SECURITY DEFINER;

Хотя это можно было бы принять, но не ясно чем я могу положиться на это в работе. В документации для SET TRANSACTION указано

Если SET TRANSACTION выполняется без до НАЧАЛА СДЕЛКИ или НАЧАТЬ, это не будет иметь никакого эффекта, поскольку транзакция будет немедленно завершена.

Что меня озадачивает, поскольку если я вызову одиночный оператор SELECT add_new_row ('foo'); , я бы ожидал (при условии, что я не отключил автокоммит), чтобы SELECT выполняться как однострочная транзакция с уровнем изоляции сеанса по умолчанию.

В руководстве также говорится:

Уровень изоляции транзакции не может быть измененным после первого запроса или оператор изменения данных (SELECT, INSERT, DELETE, UPDATE, FETCH или КОПИЯ) транзакции была

Итак, что произойдет, если функция будет вызвана из транзакции с более низким уровнем изоляции, например:

START TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE row_counts_table SET count=0;
SELECT add_new_row('foo');
COMMIT;

В качестве дополнительного вопроса: имеет ли значение язык функции? Можно ли установить уровень изоляции в PL / pgSQL иначе, чем в обычном SQL?

Я поклонник стандартов и задокументированных передовых методов, поэтому приветствуются любые достойные ссылки.

21
задан beldaz 8 June 2011 в 11:50
поделиться