2012-10-08 30 views
48

次のような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; 


誤差関数の実行中に発生した場合、すべての変更がバック圧延されるであろうか?これがデフォルトの動作ではない場合、関数をトランザクションにするにはどうすればよいですか?

+4

あなた自身でテストしてみませんか?ちょうどROLLBACKをして、あなたは答えが何であるか知っています。それは "はい"でなければなりません。 –

+8

@FrankHeikens私の質問は、 "ROLLBACKを実行した場合、ロールバックされますか" –

+2

@Don "TRUNCATE"にはあるものがある、または持っていたことに注意してくださいややファンキーな取引行動。私は詳細を覚えていません。 pgsql-generalアーカイブを検索します。 –

答えて

52

関数は、呼び出されたトランザクションの一部です。トランザクションがロールバックされると、その影響はロールバックされます。トランザクションがコミットすると、その作業がコミットされます。ファンクション内のBEGIN ... EXCEPTブロックは、SAVEPOINTおよびROLLBACK TO SAVEPOINT SQLステートメントのようにセーブポイントのように動作します(フード使用時)。

この関数はエラーハンドリングBEGIN ... EXCEPTを除いて、完全に成功するか、完全に失敗します。関数内でエラーが発生し、処理されなかった場合、関数を呼び出すトランザクションは中止されます。アボートされたトランザクションはコミットできません。コミットしようとするとCOMMITROLLBACKとして扱われ、エラーのある他のトランザクションと同じです。お守り:?

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

はエラー状態でゼロ除算が原因でトランザクションが、COMMITにロールバックする方法を参照してください。

明示的なsuroundingトランザクションなしで関数を呼び出す場合のルールは、正確に、他のPGの文と同じです:

BEGIN; 
SELECT refresh_materialized_view(name); 
COMMIT; 

SELECTは、エラーが発生した場合はどこCOMMITは失敗します)。

PostgreSQLは、呼び出し元のトランザクションとは独立して、プロシージャ/ファンクションがコミット/ロールバックできる関数で自律型トランザクションをサポートしていません(まだ)。これは、dblinkを介して新しいセッションを使用してシミュレートすることができます。

+1

非常に明確な説明。あなたの答えを短く、そして例題を説明することに感謝します。 – informatik01

17

PostgreSQLの知識がCraig Ringerの知識よりも深いので、私は短い答えを出してみます:はい。

エラーが発生した関数を実行した場合、その手順はデータベースに反映されません。

また、PgAdminでクエリを実行すると同じことが起こります。例えば

は、クエリで実行した場合:

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

select anything_that_do_not_exists; 

行の更新を、your_tableid = 20はデータベースに保存されません。

+0

明確で鮮明な答えをありがとう!クレイグの答えを読んだ後、私は不安を感じた。 – stone

+0

Craig'sよりはるかに良い答え – Nulik

3

機能レベルでは、多国籍ではありません。つまり、関数内の各ステートメントは、デフォルトのdb自動コミット値である単一のトランザクションに属します。自動コミットはデフォルトでtrueです。しかし、いずれにせよ、あなたは上記のステートメント「SCHEMANAMEを選択

select schemaName.functionName()

を使用して関数を呼び出す必要があります。functionName() 'は単一のトランザクションであり、トランザクションT1の名前をつけましょう。そのため、関数内のすべての文はトランザクションT1に属します。このように、この関数は単一のトランザクション内にあります。

0

https://www.postgresql.org/docs/current/static/plpgsql-structure.html

トランザクション制御のための同様の名前のSQLコマンドとPL/pgSQLにおける文をまとめるためのBEGIN/ENDの使用を混同しないことが重要です。 PL/pgSQLのBEGIN/ENDはグループ化のためのものです。トランザクションを開始または終了しません。関数とトリガプロシージャは、外部問合せによって確立されたトランザクション内で常に実行されます。実行するコンテキストがないため、トランザクションを開始またはコミットできません。ただし、EXCEPTION句を含むブロックは、外部トランザクションに影響を与えずにロールバックすることができます。詳細は項39.6.6を参照してください。

関連する問題