PostgreSQL 事務(wù)管理

2021-09-03 17:29 更新

在由CALL命令調(diào)用的過(guò)程中以及匿名代碼塊(DO命令)中,可以用命令COMMITROLLBACK結(jié)束事務(wù)。在一個(gè)事務(wù)被使用這些命令結(jié)束后,一個(gè)新的事務(wù)會(huì)被自動(dòng)開(kāi)始,因此沒(méi)有單獨(dú)的START TRANSACTION命令(注意 BEGINEND在PL/pgSQL中有不同的含義)。

這里是一個(gè)簡(jiǎn)單的例子:

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();

新事務(wù)開(kāi)始時(shí)具有默認(rèn)事務(wù)特征,如事務(wù)隔離級(jí)別。在循環(huán)中提交事務(wù)的情況下,可能需要以與前一個(gè)事務(wù)相同的特征來(lái)自動(dòng)啟動(dòng)新事務(wù)。 命令COMMIT AND CHAINROLLBACK AND CHAIN可以完成此操作。

只有在從頂層調(diào)用的CALLDO中才能進(jìn)行事務(wù)控制,在沒(méi)有任何其他中間命令的嵌套CALLDO調(diào)用中也能進(jìn)行事務(wù)控制。例如,如果調(diào)用棧是CALL proc1()CALL proc2()CALL proc3(),那么第二個(gè)和第三個(gè)過(guò)程可以執(zhí)行事務(wù)控制動(dòng)作。但是如果調(diào)用棧是CALL proc1()SELECT func2()CALL proc3(),則最后一個(gè)過(guò)程不能做事務(wù)控制,因?yàn)橹虚g有SELECT。

對(duì)于游標(biāo)循環(huán)有特殊的考慮。看看這個(gè)例子:

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();

通常,游標(biāo)會(huì)在事務(wù)提交時(shí)被自動(dòng)關(guān)閉。但是,一個(gè)作為循環(huán)的組成部分創(chuàng)建的游標(biāo)會(huì)自動(dòng)被第一個(gè)COMMITROLLBACK轉(zhuǎn)變成一個(gè)可保持游標(biāo)。這意味著該游標(biāo)在第一個(gè)COMMITROLLBACK處會(huì)被完全計(jì)算出來(lái),而不是逐行被計(jì)算。該游標(biāo)在循環(huán)后仍會(huì)被自動(dòng)刪除,因此這通常對(duì)用戶是不可見(jiàn)的。

有非只讀命令(UPDATE ... RETURNING)驅(qū)動(dòng)的游標(biāo)循環(huán)中不允許有事務(wù)命令。

事務(wù)在一個(gè)具有異常處理部分的塊中不能被結(jié)束。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)