若使用的是企業版,則可以額外進行 Oracle 相容的 Stored Procedure 的除錯。
這裡紀錄 EDB 10 企業版搭配 pgAdmin4 v2 設定的筆記。
Debugger 是資料庫裡面的外掛,要啟用這個功能,首先是將 debugger 在資料庫裡面啟用:要先載入相關的 Library,然後重新啟動。接著再透過前端工具進行
a. 使用 EDB 企業版資料庫
bash-4.2$ source /opt/edb/as10/pgplus_env.sh bash-4.2$ psql Password: psql.bin (10.4.9) Type "help" for help. edb=# show shared_preload_libraries; shared_preload_libraries --------------------------------------------------- $libdir/dbms_pipe,$libdir/edb_gen,$libdir/dbms_aq (1 row) edb=# edb=# -- 把上面的輸出弄下來 edb=# alter system set shared_preload_libraries ="$libdir/dbms_pipe","$libdir/edb_gen","$libdir/dbms_aq","$libdir/plugin_debugger"; ALTER SYSTEM edb=# \q bash-4.2$ bash-4.2$ # 確認一下是否最後設定的結果 bash-4.2$ cat $PGDATA/postgresql.auto.conf # Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command. shared_preload_libraries = '"$libdir/dbms_pipe", "$libdir/edb_gen", "$libdir/dbms_aq", "$libdir/plugin_debugger"' bash-4.2$ bash-4.2$ pg_ctl restart waiting for server to shut down.... done server stopped server starting bash-4.2$ 2018-05-19 01:16:52 UTC LOG: redirecting log output to logging collector process 2018-05-19 01:16:52 UTC HINT: Future log output will appear in directory "pg_log". bash-4.2$
b. 使用 EDB 提供的 PostgreSQL Distribution,設定方式基本上跟企業版一樣,只是放的位置不一樣(但仍然跟企業版填一樣的 GUC 參數),並且需要在 database 裡面啟用相關的外掛(名稱反而叫做 pldbgapi)。
bash-4.2$ ls /opt/PostgreSQL/10/lib/postgresql/ adminpack.so euc2004_sjis2004.so ltree.so plpython3.so utf8_and_euc_cn.so amcheck.so euc_cn_and_mic.so moddatetime.so pltcl.so utf8_and_euc_jp.so ascii_and_mic.so euc_jp_and_sjis.so pageinspect.so plugin_debugger.so utf8_and_euc_kr.so auth_delay.so euc_kr_and_mic.so passwordcheck.so postgres_fdw.so utf8_and_euc_tw.so auto_explain.so euc_tw_and_big5.so pg_buffercache.so refint.so utf8_and_gb18030.so autoinc.so file_fdw.so pgcrypto.so seg.so utf8_and_gbk.so bloom.so fuzzystrmatch.so pg_freespacemap.so sslinfo.so utf8_and_iso8859_1.so btree_gin.so hstore_plperl.so pgoutput.so tablefunc.so utf8_and_iso8859.so btree_gist.so hstore_plpython3.so pg_prewarm.so tcn.so utf8_and_johab.so chkpass.so hstore.so pgrowlocks.so test_decoding.so utf8_and_sjis2004.so citext.so insert_username.so pg_stat_statements.so timetravel.so utf8_and_sjis.so cube.so _int.so pgstattuple.so tsm_system_rows.so utf8_and_uhc.so cyrillic_and_mic.so isn.so pg_trgm.so tsm_system_time.so utf8_and_win.so dblink.so latin2_and_win1250.so pg_visibility.so unaccent.so uuid-ossp.so dict_int.so latin_and_mic.so pgxml.so utf8_and_ascii.so dict_snowball.so libpqwalreceiver.so pgxs utf8_and_big5.so dict_xsyn.so lo.so plperl.so utf8_and_cyrillic.so earthdistance.so ltree_plpython3.so plpgsql.so utf8_and_euc2004.so bash-4.2$
postgres=# show shared_preload_libraries; shared_preload_libraries -------------------------- (1 row) postgres=# alter system set shared_preload_libraries ="$libdir/plugin_debugger"; ALTER SYSTEM postgres=# \q bash-4.2$ pg_ctl restart
postgres=# select name from pg_available_extensions WHERE name LIKE 'p%';
name
--------------------
pg_visibility
pltclu
pgcrypto
plpgsql
pg_stat_statements
pgrowlocks
pg_freespacemap
pg_trgm
plperl
pldbgapi
plperlu
pg_buffercache
pgstattuple
pg_prewarm
plpython3u
pageinspect
postgres_fdw
pltcl
(18 rows)
postgres=# CREATE EXTENSION pldbgapi;
CREATE EXTENSION
postgres=#
c. 使用社群維護的 YUM Repo,則安裝 pldebugger 套件之後,再像前面設定一樣進行即可。
以下在 EDB 9.6 裡面弄一個小範例:這個範例,需要用 debugger 找一下問題~
下面兩個 Trigger function 會分兩次建立進去,進行個別的測試。
CREATE TABLE public.virtcol_parttab( txtid varchar(3), cnt varchar(2), partk NUMERIC(2,0), info TEXT, PRIMARY KEY (txtid, cnt) ); -- 正常的 Trigger function CREATE OR REPLACE FUNCTION public.virt_col_insert_trigger() RETURNS trigger AS $$ BEGIN IF NEW.partk IS NULL THEN NEW.partk := substr(NEW.txtid, 2, 2)::NUMERIC; END IF; RETURN NEW; END; $$ LANGUAGE 'plpgsql'; --有問題的 Trigger function,會造成 stack overflow CREATE OR REPLACE FUNCTION public.virt_col_insert_trigger() RETURNS trigger AS $$ BEGIN INSERT INTO public.virtcol_parttab VALUES (NEW.txtid, NEW.cnt, substr(NEW.txtid, 2, 2)::NUMERIC, NEW.info); RETURN NULL; END; $$ LANGUAGE 'plpgsql' ; --建立 Trigger DROP TRIGGER IF EXISTS virt_col_partitioning ON virtcol_parttab; CREATE TRIGGER virt_col_partitioning BEFORE INSERT ON public.virtcol_parttab FOR EACH ROW EXECUTE PROCEDURE public.virt_col_insert_trigger();
以下從正常的 Trigger function(綠色)開始:首先在 Trigger 按右鍵,選擇 Set Breakpoint
此時就進入等待模式,等著捕捉進來觸發這個函數的活動
方便起見,把「視窗」拉出來~
接著打開 Query Tool ,準備觸發 Trigger
這裡是觸發 Trigger 的 INSERT 指令
一按下執行紐,Debugger 內容就跑出來了
由於這是正常的 Trigger,這裡就略過~
以下的部份,是一個有問題的 Trigger function,嘗試要跟上述的功能相同,但會造成 Stack Overflow
用一樣的動作啟動 Debugger
接著按按鈕
越按越多..
這樣就可以了解,每次遇到這個 Trigger 內對自己的 INSERT 句子,就又往下開一個 Stack 進行,到最後超過 OS 預設的 Stack 最大深度,就發生 Stack Overflow 作結。
以上就是 PL/pgSQL Debugger 的示範,希望對讀者您有幫助~
如果偏好用類似 GDB 這種東西,可以考慮看看 gdb-like wrapper,pgdb~
參考資料
舊版參考
沒有留言:
張貼留言