PostgreSQL函数是事务性的吗?

hzbexzde  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(6)|浏览(198)

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;

换句话说,如果在函数执行过程中发生错误,是否会 * 回滚 * 任何更改?如果这不是默认行为,我如何使函数成为事务性的?

kgqe7b3p

kgqe7b3p1#

PostgreSQL 12更新there is limited support for top-level PROCEDURE s that can do transaction control。您仍然无法在常规的SQL可调用函数中管理事务,因此除非使用新的顶级过程,否则以下内容仍然适用。

函数是调用它们的事务的一部分。如果事务回滚,则回滚它们的影响。如果事务提交,则它们的工作也会提交。函数中的任何BEGIN ... EXCEPT块的操作类似于(并且在后台使用)保存点,如SAVEPOINTROLLBACK 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;

(如果SELECT引发错误,则COMMIT将失败)。
PostgreSQL还不支持函数中的自治事务,其中过程/函数可以独立于调用事务提交/回滚。这可以通过dblink使用新会话进行模拟。

但是,PostgreSQL中存在非事务性或不完全事务性的东西。如果它在普通的BEGIN; do stuff; COMMIT;块中具有非事务性行为,那么它在函数中也具有非事务性行为。例如,nextvalsetvalTRUNCATE等。

tag5nh1u

tag5nh1u2#

由于我对PostgreSQL的了解不如克雷格Ringer那么深,我将尝试给予一个简短的答案:是的
如果你执行一个有错误的函数,那么这些步骤都不会影响数据库。
此外,如果在PgAdmin中执行查询,也会发生同样的情况。
例如,如果在查询中执行:

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

select anything_that_do_not_exists;

your_tableid = 20行中的更新不会保存在数据库中。

2018年9月更新

为了澄清这个概念,我用非事务函数nextval做了一个小例子。
首先,让我们创建一个序列:
create sequence test_sequence start 100;
然后,让我们执行:
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)在后一个查询中使用(这是因为序列不是事务性的),尽管更新没有提交。

jchrr9hc

jchrr9hc3#

https://www.postgresql.org/docs/current/static/plpgsql-structure.html
不要将PL/pgSQL中用于分组语句的开始/END与用于事务控制的名称相似的SQL命令混淆,这一点很重要。PL/pgSQL的开始/END只用于分组;它们不开始或结束事务。函数和触发器过程总是在由外部查询建立的事务中执行-它们不能启动或提交该事务,因为没有上下文供它们执行。但是,包含EXCEPTION子句的块有效地形成了一个子事务,可以回滚该子事务而不影响外部事务。有关更多信息,请参见第39.6.6节。

esbemjvw

esbemjvw4#

在功能层面上,它不是跨国的。换句话说,函数中的每个语句都属于单个事务,这是默认的db auto commit值。默认情况下,自动提交为true。但无论如何,您必须使用
select schemaName.functionName()
上面的语句'select schemaName.functionName()'是一个事务,我们将事务命名为T1,因此函数中的所有语句都属于事务T1。这样,该函数在单个事务中。

ma8fv8wu

ma8fv8wu5#

Postgres 14更新:在过程/函数的BEGINEND块之间写入的所有语句都在单个事务中执行。因此,执行此块时出现的任何错误都将导致事务的自动回滚。

jobtbby3

jobtbby36#

此外,ATOMIC事务也包括触发器。

相关问题