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;
换句话说,如果在函数执行过程中发生错误,是否所有更改都会回滚 ? 如果这不是默认的行为,我怎样才能使交易function?
函数是它们被调用的事务的一部分。 如果交易回滚,他们的效果会回滚。 如果交易提交,他们的工作将会失败。 任何BEGIN ... EXCEPT
函数中的块都像SAVEPOINT
和ROLLBACK TO SAVEPOINT
SQL语句一样操作(并在引擎盖下使用)保存点。
该函数要么全部成功,要么全部失败,除BEGIN ... EXCEPT
error handling外。 如果在函数内发生错误而未处理,则调用该函数的事务将被中止。 中止的事务不能提交,如果他们尝试提交,则将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的了解比Craig Ringer更深刻,所以我会尽量缩短答案:是的。
如果你执行一个有错误的函数,那么这些步骤都不会影响数据库。
另外,如果您在PgAdmin
执行查询, PgAdmin
发生同样的情况。
例如,如果您在查询中执行:
update your_table yt set column1 = 10 where yt.id=20; select anything_that_do_not_exists;
your_table
id = 20
行的更新不会保存在数据库中。
在function层面上,这不是跨国的。 换句话说,函数中的每个语句都属于单个事务,这是默认的数据库自动提交值。 自动提交默认为true。 但无论如何,你必须使用这个函数
select schemaName.functionName()
上面的语句'select schemaName.functionName()'是一个单独的事务,我们命名事务T1,这样函数中的所有语句都属于事务T1。 这样,这个函数就是在一个单独的事务中。
https://www.postgresql.org/docs/current/static/plpgsql-structure.html
不要混淆使用BEGIN / END来将PL / pgSQL中的语句与用于事务控制的类似命名的SQL命令混为一谈。 PL / pgSQL的BEGIN / END仅用于分组; 他们不会开始或结束交易。 函数和触发器过程总是在由外部查询build立的事务中执行 – 它们不能启动或提交事务,因为它们没有执行的上下文。但是,包含EXCEPTION子句的块有效地形成了一个子事务在不影响外部交易的情况下回滚。 有关详情,请参阅第39.6.6节。