holdable模式可以使當前游標不被立即釋放,從而實現游標跨事務操作。本文介紹如何在存儲過程中使用holdable cursor。
背景信息
在存儲過程中使用動態游標時,PostgreSQL原生不支持將動態游標設置為holdable模式(非存儲過程中支持),如果在存儲過程中打開一個動態游標并執行事務修改保存操作后,再次嘗試獲取數據將會報錯,因為進行事務保存操作時當前事務中的游標將會被釋放。
因此PolarDB PostgreSQL版(兼容Oracle)為了滿足用戶需求,支持在PLSQL中使用holdable模式打開存儲過程游標。
PostgreSQL原生一類典型的出錯場景如下:
CREATE TABLE test001(id numeric);
INSERT INTO test001 VALUES (1), (2), (3);
CREATE OR REPLACE PROCEDURE testcur_001
IS
DECLARE
myref1 refcursor;
i numeric;
BEGIN
OPEN myref1 FOR SELECT * from test001;
commit;
fetch myref1 into i;
dbms_output.put_line(i);
close myref1;
END;
EXEC testcur_001;
DROP TABLE test001;
顯示結果如下:
ERROR: cursor "myref1" does not exist
CONTEXT: polar-spl function testcur_001() line 8 at FETCH
說明 報錯,因為myref1在commit后被自動釋放,故顯示游標myref1不存在。
使用指南
- 設置允許單個游標跨事務
在PLSQL中使用holdable模式打開單個游標的具體語法為:在OPEN語句中
FOR
前加關鍵字HOLD
。具體示例如下:CREATE TABLE test001(id numeric); INSERT INTO test001 VALUES (1), (2), (3); CREATE OR REPLACE PROCEDURE testcur_001 IS DECLARE myref1 refcursor; i numeric; BEGIN OPEN myref1 HOLD FOR SELECT * from test001; commit; fetch myref1 into i; dbms_output.put_line(i); close myref1; END; EXEC testcur_001; DROP TABLE test001;
說明 在PLSQL中使用holdable模式打開單個游標的具體語句如下:OPEN cursorname HOLD FOR SELECT ...
顯示結果如下:POLAR-SPL Procedure successfully completed
說明 加關鍵字HOLD
后,顯示POLAR-SPL程序執行成功。 - 設置允許所有游標跨事務
您需要在控制臺開啟polar_plsql_enable_holdable_refcursor參數,使您可以使用holdable模式打開所有游標。
說明- 該參數修改不需要重啟數據庫,但只對新連接生效。若您使用長連接建議修改后自行選擇時間重啟。
- 該參數默認關閉。
- 開啟后將自動將所有存儲過程中的游標設置為HOLD模式,包括顯式游標和游標變量。
- 事務塊中游標不受影響。
- 使用HOLD模式的動態游標時,請確保在當前存儲過程結束前使用
close
語句顯式關閉該游標。 - HOLD模式下的動態游標即使存儲過程結束也不會自動釋放,其消耗的內存與游標返回的查詢條目數量相關,部分情況下會寫入臨時文件。
- 大量使用
HOLD
而不關閉會對內存帶來顯著壓力,造成臨時文件堆積,也有可能導致后續的讀取數據操作變慢。