由于Oracle在2014年10月份发布 Critical Patch Update 补丁的原因,ArcGIS不能直接从Oracle实例中获取Open_Cursors参数,除非当前连接的用户有访问v$parameter 视图的权限,但是一般情况下非管理员账户是没有对该视图访问的权限。
如果地理数据库没有对Open_Cursors值的访问权限,系统就会报:ORA-01000: maximum open cursors exceeded。为了提高Oracle地理数据库的性能以及可伸缩性,Oracle 建议的最佳做法是保持游标处于打开状态, 以避免系统挣用Oracle全局区 (SGA) 的游标。
ArcGIS在很多场景下都会使用Oracle游标,比如空间查询,编辑操作、读取字典表等
由于Oracle10月份的这个CPU补丁,ArcGIS在获取Open_Cursors值时,在执行dbms_utility.get_parameter_value会碰到一个错误,如果遇到该错误,ArcGIS会检查地理数据库管理员账户中的Server_Config表中是否包含Open_Cursors字段,如果参数不存在,ArcGIS默认设置该参数值为300.
如果ArcGIS客户端连接的是一个非地理数据库的Oracle实例,连接会话仍然会执行dbms_utility.get_parameter_value,如果碰到错误,ArcGIS也会自动的为Open_cursors设为300.
但是前提是Oracle地理数据库实例中的管理员账户的Server_config表中包含Open_Cursors的字段。所以我们需要在该表中添加该字段记录,默认是没有该记录的。
该问题涉及到ArcGIS版本包括:10.1, 10.2, 10.2.1, 10.2.2, 10.3
解决方法
1:打上ArcGIS发布的最新补丁,截止到博文发布,目前补丁只有ArcGIS 10.2.2,其他版本补丁还在调试当中。
ArcGIS ‘Oracle Critical Patch Update – October 2014′ Connection Issue Patch
下载链接
2:直接使用SQL语句解决该问题(其他版本适用)
a):使用管理员账户,为地理数据库管理员对V$Parameter视图赋予权限。
GRANT SELECT ON v$parameter TO SDE;
GRANT SELECT ON v$parameter TO SDE
*
第 1 行出现错误:
ORA-02030: 只能从固定的表/视图查询
其实该视图只是一个同义词,通过以下SQL语句来说的相关表名
select synonym_name,table_name from dba_synonyms where synonym_name='V$PARAMETER';
SYNONYM_NAME TABLE_NAME
------------------------------ ------------------------------
V$PARAMETER V_$PARAMETER
然后赋予地理数据库管理员选择该表的权限即可
GRANT SELECT ON v_$parameter TO SDE;
b):使用地理管理员用户连接,执行如下存储过程,目的就是往相关地理管理员账户的Server_Config表中添加Open_Cursors值
DECLARE
rval INTEGER;
ival INTEGER := 0;
pname VARCHAR2 (256) := 'OPEN_CURSORS';
sval VARCHAR2(256);
gdb_name NVARCHAR2(256);
cprop_val VARCHAR2(256) := NULL;
c1 INTEGER;
c1_status INTEGER;
sqlstmt CLOB;
CURSOR instances_curs IS
SELECT instance_name
FROM sde.instances;
BEGIN
rval := dbms_utility.get_parameter_value(pname, ival, sval);
IF ival > 0 THEN
OPEN instances_curs;
FETCH instances_curs INTO gdb_name;
WHILE instances_curs%FOUND
LOOP
sqlstmt :=
'BEGIN '
|| gdb_name
|| '.svr_config_util.insert_server_config(:s1,:s2,:s3); '
|| 'EXCEPTION WHEN DUP_VAL_ON_INDEX THEN '
|| gdb_name
|| '.svr_config_util.update_server_config(:s1,:s2,:s3); '
|| 'END;';
IF NOT dbms_sql.is_open (c1) THEN
c1 := dbms_sql.open_cursor;
END IF;
dbms_sql.parse (c1, TO_CHAR (sqlstmt), dbms_sql.native);
dbms_sql.bind_variable (c1, ':s1', pname);
dbms_sql.bind_variable (c1, ':s2', cprop_val);
dbms_sql.bind_variable (c1, ':s3', ival);
c1_status := dbms_sql.execute (c1);
dbms_sql.close_cursor (c1);
FETCH instances_curs INTO gdb_name;
END LOOP;
CLOSE instances_curs;
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
/
c):然后再取消该地理管理员对V$PARAMETER的执行权限
REVOKE SELECT ON v_$parameter FROM SDE;
接下来,我们查看Server_Config表里面的值,发现已经有Open_Cursors项,当然默认的300可能比较少,根据情况可以直接增大到2000.