Являются ли функции PostgreSQL транзакционными?

Является ли функция PostgreSQL, например, следующая автоматически транзакционной?

CREATE OR REPLACE FUNCTION refresh_materialized_view(name)
  RETURNS integer AS
$BODY$
 DECLARE
     _table_name ALIAS FOR $1;
     _entry materialized_views%ROWTYPE;
     _result INT;
 BEGIN          

     EXECUTE 'TRUNCATE TABLE ' || _table_name;

     UPDATE materialized_views
     SET    last_refresh = CURRENT_TIMESTAMP
     WHERE  table_name = _table_name;

     RETURN 1;
END
$BODY$
  LANGUAGE plpgsql VOLATILE SECURITY DEFINER;



Другими словами, если во время выполнения функции произойдет ошибка, будут ли какие-либо измененияоткат? Если это неповедение по умолчанию, как я могу сделать функциюна транзакциях?

 Craig Ringer08 окт. 2012 г., 11:25
@ Знай, чтоTRUNCATE имеет или имел какое-то странное транзакционное поведение. Я непомните специфику; поиск в pgsql-общих архивах.
 Dónal08 окт. 2012 г., 11:04
@FrankHeikens мой вопрос "изменения будут автоматически отменены после ошибки ", скорее, чем "будут ли отменены изменения, если я выполню ROLLBACK "
 G_V09 мар. 2018 г., 12:21
@ CraigRinger Насколько я могу судитьTRUNCATE игнорирует все точки сохранения и просто полностью уничтожает данные таблицы
 Frank Heikens08 окт. 2012 г., 10:55
Почему Дон'ты сам это проверял? Просто сделайте откат, и вы знаете, что ответ. Так должно быть "да".
 ma11hew2815 мар. 2014 г., 18:37
Да, функции являются транзакционными, даже если они написаны на.LANGUAGE SQL

Ответы на вопрос(3)

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

select schemaName.functionName()

Вышеуказанное утверждениевыберите schemaName.functionName () ' это одна транзакция, пустьНазовите транзакцию T1, поэтому все операторы в функции принадлежат транзакции T1. Таким образом, функция находится в одной транзакции.

Поскольку мои знания PostgreSQL менее глубоки, чем у Крейга Рингераs Я постараюсь дать более короткий ответ: Да.

Если вы выполняете функцию с ошибкой, ни один из шагов не повлияет на базу данных.

Кроме того, если вы выполняете запрос вPgAdmin то же самое случилось

Например, если вы выполняете запрос:

update your_table yt set column1 = 10 where yt.id=20;

select anything_that_do_not_exists;

Обновление в строке,id = 20 изyour_table не будут сохранены в базе данных.

ОБНОВЛЕНИЕ сентябрь - 2018

Чтобы прояснить концепцию, я сделал небольшой пример с нетранзакционной функцией nextval.

Во-первых, давайтеСоздайте последовательность:

create sequence test_sequence start 100;

Тогда давайs выполнить:

update your_table yt set column1 = 10 where yt.id=20; select nextval('test_sequence'); select anything_that_do_not_exists;

Теперь, если мы откроем еще один запрос и выполните

select nextval('test_sequence');

Мы получим 101, потому что первое значение (100) использовалось в последнем запросе (то есть, потому что последовательности не являются транзакционными), хотя обновление не было зафиксировано.

 Craig Ringer16 мар. 2018 г., 14:38
Остерегайтесь нетранзакционных вещей, таких какnextval хоть; если они'не транзакционные или не полностью транзакционные, как обычные запросы, они нет в функции тоже.
 Ignacio19 мар. 2018 г., 14:46
Спасибо за обновление, Крейг!
 Nulik17 янв. 2017 г., 16:22
гораздо лучший ответ, чем у Крейга
 stone08 янв. 2017 г., 01:43
Спасибо за четкий четкий ответ! После прочтения КрейгаОт ответа я остался неуверенным.

Функции являются частью транзакции, которую ониперезвонил из. Их эффекты откатываются, если транзакция откатывается. Их работа фиксируется, если транзакция фиксируется. любойBEGIN ... EXCEPT блоки внутри функции работают как (и под капотом) как точки сохраненияSAVEPOINT а такжеROLLBACK TO SAVEPOINT Операторы SQL.

Функция либо завершается успешно, либо завершается с ошибкой целиком, за исключениемBEGIN ... EXCEPT обработка ошибок. Если в функции возникает ошибка, которая не обрабатывается, транзакция, вызывающая функцию, прерывается. Прерванные транзакции не могут быть зафиксированы, и если они пытаются зафиксироватьCOMMIT рассматривается какROLLBACKТак же, как и для любой другой транзакции с ошибкой. Заметим:

regress=# BEGIN;
BEGIN
regress=# SELECT 1/0;
ERROR:  division by zero
regress=# COMMIT;
ROLLBACK

Посмотрите, как откатывается транзакция, которая находится в состоянии ошибки из-за деления на ноль?COMMIT

Если вы вызываете функцию без явной окружающей транзакции, правила точно такие же, как и для любого другого оператора Pg:

BEGIN;
SELECT refresh_materialized_view(name);
COMMIT;

(гдеCOMMIT потерпит неудачу, еслиSELECT поднял ошибку).

PostgreSQL (пока) не поддерживает автономные транзакции в функциях, где процедура / функция может фиксировать / откатывать независимо от вызывающей транзакции. Это может быть смоделировано с использованием нового сеанса черезDBLink.

НОвещи, которые неt Транзакционные или несовершенно транзакционные существуют в PostgreSQL. Если он имеет нетранзакционное поведение в нормальномBEGIN; do stuff; COMMIT; блок, он также имеет нетранзакционное поведение в функции. Например,nextval а также ,setvalTRUNCATE, так далее.

 informatik0130 нояб. 2016 г., 15:15
Очень четкое объяснение. Отдельное спасибо за иллюстрирование вашего ответа короткими и точными примерами.

Ваш ответ на вопрос