2025年9月25日: PostgreSQL 18 釋出!
支援的版本:當前 (18) / 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)。

提交更正

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