支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不再支援的版本:12 / 11

41.8. 交易管理 #

在由 CALL 指令調用的程序以及匿名程式碼區塊(DO 指令)中,可以使用 COMMITROLLBACK 指令來結束交易。在使用這些指令結束交易後,會自動啟動新的交易,因此沒有單獨的 START TRANSACTION 指令。(請注意,BEGINEND 在 PL/pgSQL 中具有不同的含義。)

這是一個簡單的範例

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END;
$$;

CALL transaction_test1();

新的交易會以預設的交易特性(例如交易隔離等級)啟動。在迴圈中提交交易的情況下,可能需要使用與先前交易相同的特性自動啟動新的交易。COMMIT AND CHAINROLLBACK AND CHAIN 指令可以實現此目的。

交易控制僅可能在頂層的 CALLDO 調用中,或者在沒有任何其他介入指令的巢狀 CALLDO 調用中。例如,如果調用堆疊是 CALL proc1()CALL proc2()CALL proc3(),那麼第二個和第三個程序可以執行交易控制動作。但是,如果調用堆疊是 CALL proc1()SELECT func2()CALL proc3(),則由於中間的 SELECT,最後一個程序無法進行交易控制。

PL/pgSQL 不支援儲存點(SAVEPOINT/ROLLBACK TO SAVEPOINT/RELEASE SAVEPOINT 指令)。儲存點的典型使用模式可以用帶有例外處理器的區塊來替換(請參閱第 41.6.8 節)。在底層,帶有例外處理器的區塊會形成一個子交易,這意味著不能在這樣的區塊內結束交易。

特殊考慮適用於游標迴圈。考慮以下範例

CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN SELECT * FROM test2 ORDER BY x LOOP
        INSERT INTO test1 (a) VALUES (r.x);
        COMMIT;
    END LOOP;
END;
$$;

CALL transaction_test2();

通常,游標會在交易提交時自動關閉。但是,像這樣在迴圈中建立的游標會在第一次 COMMITROLLBACK 時自動轉換為可保持的游標。這意味著游標會在第一次 COMMITROLLBACK 時被完全評估,而不是逐行評估。游標仍然會在迴圈後自動移除,因此這對於使用者來說幾乎是不可見的。但是必須記住,游標查詢所取得的任何表鎖定或行鎖定,在第一次 COMMITROLLBACK 後將不再保持。

不允許在由非唯讀指令驅動的游標迴圈中使用交易指令(例如 UPDATE ... RETURNING)。

提交更正

如果您在文件中發現任何不正確、與您特定功能的使用經驗不符或需要進一步澄清的地方,請使用此表單來報告文件問題。