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
而不关闭会对内存带来显著压力,造成临时文件堆积,也有可能导致后续的读取数据操作变慢。