最近一直接到售前的请求,客户现场成功部署SDEfor Oracle后,在部署SQL直接操作空间数据的时候始终无法配置成功,现把SQL访问空间数据的原理以及配置过程中经常碰到的问题详细的介绍一下。

ORA-28595: Extproc 代理: DLL 路径无效
 ORA-06512: 在 "SDE.ST_GEOMETRY_SHAPELIB_PKG", line 70
 ORA-06512: 在 "SDE.ST_GEOMETRY_OPERATORS", line 68

 View program sources of error stack?
 --------------------------
 listener.ora:

 SID_LIST_LISTENER =
   (SID_LIST =
     (SID_DESC =
       (SID_NAME = PLSExtProc)
       (ORACLE_HOME = F:\oracle\product\10.2.0\db_1)
       (PROGRAM = extproc)
      (ENVS="EXTPROC_DLLS=E:\ArcGIS\ArcSDE\ora10gexe\bin\st_shapelib.dll")---这个“E:\ArcGIS\ArcSDE\ora10gexe\bin\st_shapelib.dll”是可以在本机打开找到文件的
    )
     (SID_DESC =
        (GLOBAL_DBNAME = webgis)
        (ORACLE_HOME = F:\oracle\product\10.2.0\db_1)
        (SID_NAME = webgis )
    )
   )

 LISTENER =
   (DESCRIPTION_LIST =
     (DESCRIPTION =
       (ADDRESS = (PROTOCOL = TCP)(HOST =10.238.185.71)(PORT = 1521))
     )
     (DESCRIPTION =
       (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
     )
   )
 --------------------
 tnsname.ora:

 EXTPROC_CONNECTION_DATA =
   (DESCRIPTION =
     (ADDRESS_LIST =
       (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
     )
     (CONNECT_DATA =
       (SID = PLSExtProc)
       (PRESENTATION = RO)
     )
   )
 WEBGIS =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCP)(HOST = 10.238.185.71)(PORT = 1521))
     (CONNECT_DATA =
       (SERVER = DEDICATED)
       (SERVICE_NAME = webgis)
     )
   )

 ---------------

 C:\Documents and Settings\Administrator>tnspingEXTPROC_CONNECTION_DATA ---这里也是通的
 TNS Ping Utility for 32-bit Windows: Version 10.2.0.4.0 - Production on 07-9月 -
 2011 12:30:55
 Copyright (c) 1997,  2007, Oracle.  All rights reserved.
 已使用的参数文件:
 F:\oracle\product\10.2.0\db_1\network\admin\sqlnet.ora

 已使用 TNSNAMES 适配器来解析别名
 Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL =IPC)
 (KEY = EXTPROC0))) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO)))
 OK (0 毫秒)

原理

从ArcSDE9.2 for oracle开始,提供了使用直接调用SQL来操作空间数据的方法,但是得进行配置才能使用,而且空间数据的存储方式只能是ST_GEOMETRY才支持直接SQL。

由于这些空间操作的函数都是GIS的核心算法,并且这些算法都是非常消耗CPU的算法,所以ESRI是以动态库而不是PL/SQL(适用于批量数据处理)的方式提供的这部分函数,然后在oracle中使用C的externalprocedure对动态库进行调用。

调用过程如下:

1. 用户进程执行SQL,在sqlplus执行selectsde.st_astext(shape) from sde.test,在数据库中调用的顺序是:

SQL Server网络配置 1433不能选择启动_oracle

上述三个对象的定义如下

sde.astext:

 

SQL Server网络配置 1433不能选择启动_动态库_02

CREATEOR REPLACE PACKAGE BODY "SDE"."ST_GEOMETRY_OPERATORS"
IS
--st_Astext
Functionst_astext_f(prim SDE.st_geometry)
Returnclob
IS
sprefSDE.spx_util.spatial_ref_record_t;
tempvarchar2(1);
text_clobclob := empty_clob();
rcnumber;
Begin
If primIS NULL THEN
Return NULL;
End If;
Ifprim.numpts = 0 and prim.entity = 0 Then
text_clob:= 'EMPTY';
return(text_clob);
End If;
spref.srid:= prim.srid;
rc :=SDE.st_spref_util.select_spref(spref);
If rc!= SDE.st_type_user.se_success THEN
raise_application_error(SDE.st_type_util.st_no_srid,'srid '||spref.srid||
' doesnot exist in st_spatial_references table.');
End If;
text_clob:= ' ';
SDE.st_geometry_shapelib_pkg.astext(spref.srid,spref.x_offset,spref.y_offset,spref.xyunits,spref.z_offset,
spref.z_scale,spref.m_offset,spref.m_scale,spref.Definition,prim.numpts,
prim.entity,prim.points,text_clob);
Return(text_clob);
Endst_astext_f;
Sde.st_geometry_shapelib_pkg.st_astext的存储过程的代码如下:
CREATEOR REPLACE PACKAGE BODY "SDE"."ST_GEOMETRY_SHAPELIB_PKG" AS
Procedureastext (srid IN number,
false_xIN number,
false_yIN number,
xyunitsIN number,
false_zIN number,
zunitsIN number,
false_mIN number,
munitsIN number,
proj_strIN varchar2,
pls_numptsIN number,
pls_entityIN number,
pointsIN blob,
shptxtIN Out clob
)
AS
languagec
name"AsText"
libraryst_shapelib
WITHCONTEXT
parameters(
CONTEXT,
sridocinumber,
false_xocinumber,
false_yocinumber,
xyunitsocinumber,
false_zocinumber,
zunitsocinumber,
false_mocinumber,
munitsocinumber,
proj_strstring, proj_str Indicator short, proj_str length int,
pls_numptsocinumber,
pls_entityocinumber,
pointsociloblocator, points Indicator short,
shptxtociloblocator, shptxt Indicator short
)

2。在执行的Sde.st_geometry_shapelib_pkg.st_astext程序过程中,调用了一个astext函数(该函数在SDEHOME/bin/st_shapelib.dll(windows),$SDEHOME/lib/libst_shapelib.so(unix,linux)定义的)。这里需要借助别名库(AliasLibrary)来表示动态库路径。别名库是数据库里的一个对象,在SDE中就是st_shapelib对象(该对象的类型为library对象,其定义在下面),用来描述一个外部函数所在的动态链接库的路径和名称。通过别名库,从而可以知道被调用的外部函数在哪个文件里。

Library对象的定义:

Windows:

 

SQL Server网络配置 1433不能选择启动_动态库_03

Linux,Unix:

 

SQL Server网络配置 1433不能选择启动_ci_04

Astext函数的定义:

Windows:

 

SQL Server网络配置 1433不能选择启动_oracle_05

从上图可以看出,空间运算的所有的核心算法都在这17个函数中。

Linux,Unix:

 

SQL Server网络配置 1433不能选择启动_数据库服务器_06

3.当某个session调用某个sql的时候,监听器会生成一个ext(extproc.exewindows,extproc(linux))该进程专门用来处理对外部函数的调用。并且在整个session生命周期里,extproc进程会一直存在,只有当所有的session断开后,该进程才会退出。

4.Extproc进程负责将别名库所指定的动态链接库文件加载到内存,(windows:st_shapelib.dll,unix,linux:libst_shapelib.so必须放在数据库服务器端,并且由于windows:st_shapelib.dll要调用sg.dll和pe.dll两个动态库,unix,linux:libst_shapelib.so要调用libsg.so,libpe.so两个动态库,所以相关的两个动态库也要放到服务器端)

5.Extproc进程执行指定的外部函数,并将结果返回给服务器进程,进而服务器进程返回给用户进程。

 

从上述原理可以看到,使用外部存储过程,既保证了调用的效率,又很好的隐藏了源代码。

配置
st_shapelib对象的配置

该对象位于sde的schema下,类型为library,以sde用户登陆后可以通过查询user_libraries字典进行详细信息的查询。

分以下几种情况进行说明:

1.ArcSDE和数据库服务器安装在一台机器。

在post过程中会自动创建该对象,而且该对象指向的外部的动态库的路径一定正确的,对这种情况不用做特别的设置。

2.ArcSDE和数据库服务器是分开部署的并且数据库服务器和sde服务器是同类型,同厂商的操作系统,如都是windows操作系统或者都是solairs操作系统。

在post过程中也会自动创建该对象,但是该对象所指向的外部的动态库为sde服务器上的路径,如sde安装在d:/program/arcgis/arcsde目录中,则该对象指向d:/programfiles/arcgis/arcsde/ora10gexe/bin/st_shapelib.dll,但是该路径在数据库服务上并不存在,此时可以用以下两种方法进行处理。

A. 在数据库服务器上也建立d:/programfiles/arcgis/arcsde/ora10gexe/bin/目录,然后把sde服务器上的st_shapelib.dll文件拷贝到该目录中。

B. 在数据库服务器上随便建立一个目录,如d:/arcsde/bin,然后把sde服务器上的st_shapelib.dll文件拷贝到该目录中,然后到数据库中修改st_shapelib对象所指向的动态库,

 

SQL Server网络配置 1433不能选择启动_oracle_07

3.ArcSDE和数据库服务器是分开部署的,并且数据库服务器和sde服务器不是同类型的操作系统。

如数据库服务器是linux,sde服务器是window操作系统。

如sde安装在d:/programfiles/arcgis/arcsde目录中,做完post后,数据库中的st_shapelib对象所指向的动态库为d:/programfiles/arcgis/arcsde/ora10gexe/bin/st_shapelib.dll。该路径在linux实际上不存在。此时需要在数据库服务器上把ArcSDE的软件安装上,然后通过sql到数据库中把st_shapelib对象指向正确的动态库。

Oracle外部存储过程的配置
配置方法

数据库服务器端:

Windows操作系统下通过菜单打开netmanager, linux, unix操作系统执行netmgr,启动的界面如下图所示:

1.

选中已经存在的某个listener(一般情况下只会有一个listener),选择监听位置,并添加一个监听地址,协议选择IPC,如下图所示:

SQL Server网络配置 1433不能选择启动_oracle_08

2. 然后选择数据库服务,并填写相关信息,如下:

 

SQL Server网络配置 1433不能选择启动_oracle_09

3. 选择其他服务,

在环境处填写:

"EXTPROC_DLLS=d:/programfiles/arcgis/arcsde/ora10gexe/bin/st_shapelib.dll"
在程序名处填写:
extproc
SID处填写:
PLSExtProc

 

SQL Server网络配置 1433不能选择启动_动态库_10

3. 选择文件à保存网络配置后,退出,完成监听器的配置。

4. 修改tnsnames.ora文件,添加如下一行:

EXTPROC_CONNECTION_DATA=
(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS= (PROTOCOL = IPC)(Key = EXTPROC1))
(ADDRESS= (PROTOCOL = TCP)(HOST = 192.168.200.222)(PORT = 1521))
)
(CONNECT_DATA=
(SID =PLSExtProc)
(PRESENTATION= RO)
)
)

 

常见问题

1.Linux,Unix下没有把$SDEHOME/lib目录添加到oracle用户下的.profile或者.bash_profile的相关环境变量中。

2. 监听器除了监听TCP协议,一定还要要监听IPC协议,可以通过lsnrctlstatus命令来查看。

3.St_shapelib对象所指向的动态库的路径不正确,可以通过select* from user_libraries查看指向的动态库的路径是否正确,如果不正确可以通过createor replace library st_shapelib as ‘your lib path’来修改。