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;
즉, 함수 실행 중에 오류가 발생하면 변경 사항이 롤백 됩니까? 이것이 기본 동작이 아니라면 어떻게 함수를 트랜잭션으로 만들 수 있습니까?
PostgreSQL 12 업데이트 : 트랜잭션 제어를 수행 할 수있는 최상위 수준에 대한 지원이 제한 PROCEDURE
되어 있습니다 . 일반 SQL 호출 가능 함수에서는 여전히 트랜잭션을 관리 할 수 없으므로 새로운 최상위 프로 시저를 사용할 때를 제외하고는 아래 내용이 그대로 유지됩니다.
함수는 호출되는 트랜잭션의 일부입니다. 트랜잭션이 롤백되면 그 효과가 롤백됩니다. 트랜잭션이 커밋되면 작업이 커밋됩니다. 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
0 분할로 인해 오류 상태에있는 트랜잭션이 어떻게 롤백되는지 확인하십시오 COMMIT
.
명시적인 주변 트랜잭션없이 함수를 호출하는 경우 규칙은 다른 Pg 문과 정확히 동일합니다.
BEGIN;
SELECT refresh_materialized_view(name);
COMMIT;
( 오류 COMMIT
가 발생하면 실패합니다 SELECT
).
PostgreSQL은 (아직) 함수에서 자동 트랜잭션을 지원하지 않습니다. 여기서 프로 시저 / 함수는 호출 트랜잭션과 독립적으로 커밋 / 롤백 할 수 있습니다. 이것은 dblink 를 통해 새 세션을 사용하여 시뮬레이션 할 수 있습니다 .
하지만 트랜잭션이 아니거나 불완전한 트랜잭션이 PostgreSQL에 존재합니다. 일반 BEGIN; do stuff; COMMIT;
블록에서 비 트랜잭션 동작이있는 경우 함수에서도 비 트랜잭션 동작이 있습니다. 예를 들어, nextval
그리고 setval
, TRUNCATE
등
PostgreSQL에 대한 나의 지식이 Craig Ringer의 지식보다 덜 깊기 때문에 나는 더 짧은 대답을하려고 노력할 것입니다 : 예.
오류가있는 함수를 실행하면 어떤 단계도 데이터베이스에 영향을주지 않습니다.
또한 PgAdmin
동일한 쿼리를 실행하면 발생합니다.
예를 들어 쿼리에서 실행하는 경우 :
update your_table yt set column1 = 10 where yt.id=20;
select anything_that_do_not_exists;
행의 업데이트는, id = 20
의 your_table
데이터베이스에 저장되지 않습니다.
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');
업데이트가 커밋되지 않았지만 첫 번째 값 (100)이 후자의 쿼리 (즉, 시퀀스가 트랜잭션이 아니기 때문에)에서 사용 되었기 때문에 101을 얻습니다.
In the function level, it is not transnational. In other words, each statement in the function belongs to a single transaction, which is the default db auto commit value. Auto commit is true by default. But anyway, you have to call the function using
select schemaName.functionName()
The above statement 'select schemaName.functionName()' is a single transaction, let's name the transaction T1, and so the all the statements in the function belong to the transaction T1. In this way, the function is in a single transaction.
https://www.postgresql.org/docs/current/static/plpgsql-structure.html
It is important not to confuse the use of BEGIN/END for grouping statements in PL/pgSQL with the similarly-named SQL commands for transaction control. PL/pgSQL's BEGIN/END are only for grouping; they do not start or end a transaction. Functions and trigger procedures are always executed within a transaction established by an outer query — they cannot start or commit that transaction, since there would be no context for them to execute in. However, a block containing an EXCEPTION clause effectively forms a subtransaction that can be rolled back without affecting the outer transaction. For more about that see Section 39.6.6.
참고URL : https://stackoverflow.com/questions/12778209/are-postgresql-functions-transactional
'Programing' 카테고리의 다른 글
HttpClient에서 압축 해제 전에 압축 된 데이터에 액세스 할 수 있습니까? (0) | 2020.11.19 |
---|---|
왜 SortedSet인가 (0) | 2020.11.19 |
Git에서 .classpath 및 .project 무시 (0) | 2020.11.18 |
작업자 역할과 웹 작업 (0) | 2020.11.18 |
Spring CORS 'Access-Control-Allow-Origin'헤더가 없습니다. (0) | 2020.11.18 |