這和子交易(Sub-Transaction)是不同的概念:子交易和上層的交易是巢狀的概念,仍然是單一個工作程序,在子交易中發生 Rollback,就對整個交易都會 Rollback;而 Autonomous Transaction 則是在呼叫之時,額外分支出另外一個交易執行,分之出去的交易活動成敗(Commit/Rollback)不會再影響目前的交易,兩者獨立開來。
在 Oracle 的 Stored Procedure 中,有一個 PRAGMA AUTONOMOUS_TRANSACTION 的修飾字,讓一個函數的運行,額外分支出一個交易。
不過到 Postgres 9.6 為止,都沒有「直接」支援這樣的功能,那在 Postgres 9.6 要如何做到呢?
在 PostgreSQL 中要作到從當前交易中再獨立出一個交易,有兩個方法:
- 使用 dblink 模組,把要分支的 SQL 指令,額外再連線到資料庫運行
- 在 Postgres 9.5 之後社群有提供一個套件,叫做 pg_background,直接提供相關的函數處理 Autonomous Transaction
以下會紀錄 pg_background 的使用筆記。
這是一個社群外掛,需要自己編譯與安裝(需要使用 root 帳號)。這裡用 EDB 的 Postgres 企業版作示範。
編譯之前,先安裝需要的編譯套件
bash-# yum install -y openssl-devel
我們需要讓目前的 Shell 找的到 pg_config 指令位置,在 EDB 的 Postgres 發行版中,可以載入一個附贈的 Shell Script 即可。
bash-# source /opt/edb/as9.6/pgplus_env.sh
然後是下載與安裝:中間過程就不附上了
bash-# wget https://codeload.github.com/vibhorkum/pg_background/zip/master -O pg_background-master.zip bash-# unzip pg_background-master.zip bash-# cd pg_background-master/ bash-# bash-# make USE_PGXS=1 bash-# make install
安裝完畢後,進入資料庫,在資料庫裡面啟用模組,就可以開始使用
CREATE EXTENSION pg_background;
pg_background 的運作,是直接分支出一個 Process 來處理,然後告訴你正在執行該請求的 PID(Process ID)。它提供三個 API,分別是送出 SQL 指令(pg_background_launch('SQL COMMAND') ),與取得回傳結果(pg_background_result (pid)),以及不取回結果直接釋放程序(pg_background_detach(pid))。
以下簡單示範一下
CREATE FUNCTION fork_test(sql_str TEXT) RETURNS int AS $$ DECLARE result_pid INT; BEGIN SELECT * INTO result_pid FROM pg_background_launch(sql_str); RETURN result_pid; END $$ LANGUAGE plpgsql;
edb=# SELECT fork_test('select empno,ename from emp');
fork_test
-----------
3586
(1 row)
edb=# SELECT * FROM pg_background_result(3586) AS (number numeric,name varchar);
number | name
--------+--------
7369 | SMITH
7499 | ALLEN
7521 | WARD
7566 | JONES
7654 | MARTIN
7698 | BLAKE
7782 | CLARK
7788 | SCOTT
7839 | KING
7844 | TURNER
7876 | ADAMS
7900 | JAMES
7902 | FORD
7934 | MILLER
(14 rows)
edb=# WITH forkpid AS(
SELECT pid
FROM pg_sleep(20), -- 暫停一下
fork_test('select empno,ename from emp') as pid
)
SELECT * FROM forkpid f, pg_background_result(f.pid) AS (number numeric,name varchar);
pid | number | name
------+--------+--------
3860 | 7369 | SMITH
3860 | 7499 | ALLEN
3860 | 7521 | WARD
3860 | 7566 | JONES
3860 | 7654 | MARTIN
3860 | 7698 | BLAKE
3860 | 7782 | CLARK
3860 | 7788 | SCOTT
3860 | 7839 | KING
3860 | 7844 | TURNER
3860 | 7876 | ADAMS
3860 | 7900 | JAMES
3860 | 7902 | FORD
3860 | 7934 | MILLER
(14 rows)
目前已知這個模組計畫要引進資料庫核心了,不過可能會改變一下面貌,用新的呼叫方式出現。至於使用方法,等未來引進之後再說吧~
參考資料
沒有留言:
張貼留言