2012-10-08 42 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 @frankHeikens我的問題是「將在錯誤發生後自動回滾」,而不是「如果我執行ROLLBACK將會回滾更改」 –

+2

@Don請注意'TRUNCATE'有或曾經有一些有些時髦的交易行爲。我不記得具體細節;搜索pgsql-general檔案。 –

回答

52

函數是它們被調用的事務的一部分。如果交易回滾,它們的效果會回滾。如果交易提交,他們的工作將會失敗。該函數中的任何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

如果你調用一個函數沒有明確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

比克雷格的答案好得多 – Nulik

3

在功能層面,它不是跨國的。換句話說,函數中的每個語句都屬於單個事務,這是默認的數據庫自動提交值。自動提交默認爲true。但無論如何,你必須調用使用

select schemaName.functionName()

上面的語句「選擇SCHEMANAME功能。functionName()'是一個單獨的事務,我們來命名事務T1,這樣函數中的所有語句都屬於事務T1。通過這種方式,該功能在單個事務中。

0

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

不要混淆使用開始/結束的分組報表PL/pgSQL裏有類似命名的SQL這是很重要的事務控制命令。 PL/pgSQL的BEGIN/END僅用於分組;他們不會開始或結束交易。函數和觸發器過程始終在由外部查詢建立的事務中執行 - 它們無法啓動或提交該事務,因爲它們不會執行任何上下文。但是,包含EXCEPTION子句的塊有效地形成了一個子事務在不影響外部交易的情況下回滾。有關詳情,請參閱第39.6.6節。