這和子交易(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)
目前已知這個模組計畫要引進資料庫核心了,不過可能會改變一下面貌,用新的呼叫方式出現。至於使用方法,等未來引進之後再說吧~
參考資料
沒有留言:
張貼留言