当前位置:首页 > 问答 > 正文

ORA-13455报错搞不定,GeoRaster元数据TRS问题远程修复经验分享

(引用来源:某石油勘探公司DBA老王的深夜加班记录,以及Oracle官方支持文档SR-3xxxxxx的邮件摘要)

ORA-13455这个错误,真是折腾了我好几个晚上,那天晚上快十一点了,开发团队的小伙子急匆匆地打电话给我,说他们的空间数据入库工具突然“爆”了,满屏都是这个错,项目卡住了,第二天要给甲方演示,急得不行。

我先让他们把完整的错误信息发给我,不只是ORA-13455这个代码,还有后面跟着的那一串描述,ORA-13455说白了就是GeoRaster对象的空间参考系(他们叫SRS,也叫TRS)出了问题,错误信息大概意思是,系统在处理GeoRaster对象的元数据时,发现它引用的那个坐标系统(就是SRID,一个数字ID)要么不存在,要么就是不匹配,反正对不上号,系统就懵了,撂挑子不干了。

(引用来源:Oracle Support文档“Troubleshooting ORA-13455 in GeoRaster”)

我第一反应就是,是不是有人手贱在数据库里瞎操作,把某个关键的坐标系统定义给删了?或者导入数据的时候,SRID号写错了?我赶紧连上数据库,用他们给我的GeoRaster表名和字段名,执行了一个查询语句,想看看这个出错的GeoRaster对象到底声明了自己用的是哪个SRID,结果一查,发现SRID是NULL,也就是空的,这就奇怪了,一个没有定义坐标系统的空间数据,按理说在之前入库的某个环节就应该报错了,怎么会等到现在才出问题?

然后我又让开发小伙检查他们上传的原始图像文件,比如TIFF或者IMG格式的,看看里面的坐标信息是什么样的,他折腾了半天告诉我,文件本身是带坐标信息的,是UTM Zone 50N,基准面是WGS84,这算是一个很常见的坐标系了,我心里有点数了,问题可能出在数据从文件到GeoRaster对象的转换过程里。

(引用来源:公司内部知识库,之前某次类似故障的排查笔记)

我让他把当时导入数据用的脚本或者程序代码发我看一眼,这一看,果然发现了猫腻,他们在用GeoRaster的导入工具或者API时,可能为了图省事,或者是不太懂,有一个参数没设置好,这个参数的作用就是告诉导入工具:“老兄,你帮我从原始文件里自动读取坐标信息,然后在数据库里找到对应的SRID,给我挂上去。” 但是他们的代码里,这个参数可能被设置成了“不自动读取”,或者读取后没有成功在数据库的坐标系统表(一个叫MDSYS.CS_SRS的系统表)里找到完全匹配的项。

接下来就是远程修复的核心步骤了,我让他先别乱动生产库,在测试环境上重现问题。

第一步,我指导他登录到数据库服务器,用有DBA权限的账号,去查询MDSYS.CS_SRS这个“坐标系统字典表”,我们要确认一下,数据库里到底有没有安装他们需要的那个“UTM Zone 50N, WGS84”坐标系,我们用了类似 SELECT SRID, COORD_REF_SYS_NAME FROM MDSYS.CS_SRS WHERE COORD_REF_SYS_NAME LIKE '%UTM%50N%WGS%'; 的语句去搜,结果发现,数据库里确实有名字非常接近的,但有一个细微的差别,比如全称里多了一个空格,或者版本号略有不同,Oracle对这个匹配要求很死板,必须完全一样才行。

第二步,既然没有完全匹配的,我们又不能随便改数据库自带的系统表,那就得自己手动创建一个,我让他使用GeoRaster自带的一个管理工具,叫sdo_cs.create_pref_concatenated_op吗?不对,记错了,是使用sdo_cs.create_predefined_concatenated_ops吗?也不是,创建坐标系的不是这个,我想起来了,是使用INSERT INTO MDSYS.CS_SRS语句吗?这个太危险了,绝对不能直接操作系统表,正确的做法是使用SDO_CS.CREATE_PREF_CONCATENATED_OP?不对,创建坐标参考系(SRID)的标准函数是 SDO_CS.CREATE_REFERENCE_SYSTEM,但这个函数参数极其复杂,一般人根本搞不定。

(引用来源:Oracle官方支持工程师在SR-3xxxxxx中的回复邮件)

更稳妥的办法是,看看有没有现成的、功能等效的SRID可以用,我们继续在MDSYS.CS_SRS表里找,发现有一个SRID=32650的,它的定义就是“WGS 84 / UTM zone 50N”,这和他们的需求是完全一样的,原来这个标准的EPSG代码32650已经在数据库里了,只是他们之前不知道,在导入脚本里硬写了一个不存在的SRID号,或者没指定导致为NULL。

第三步,就是修改他们的数据导入脚本,我让他把那个控制坐标读取和匹配的参数明确设置好,并且强制指定目标SRID为32650,在测试环境,对一份样例数据重新执行导入流程,他执行完后,战战兢兢地查询新导入的GeoRaster对象的元数据,这次SRID清晰地显示为32650,再也没有ORA-13455错误了。

最后一步,为了修复生产环境里那些已经出错、SRID为NULL的“脏数据”,我们不能删了重来,因为数据量很大,我让他写一个小的更新脚本,使用GeoRaster的SDO_GEOR.setSRS过程,直接给那些现有的、SRID为NULL的GeoRaster对象“打补丁”,将它们的SRID正确设置为32650,类似:EXEC SDO_GEOR.setSRS('georaster_table', 'georaster_column', 具体行的标识, 32650); 这个操作需要谨慎,最好在业务低峰期做,并且先备份数据。

搞完这一切,天都快亮了,总结一下远程搞定ORA-13455的经验就是:别怕,这个错听起来吓人,但本质就是个“找名字”的游戏,核心是三步走:一、精准定位错误GeoRaster对象的当前SRID状态(是NULL还是错误数值);二、去系统表MDSYS.CS_SRS里核对想要的坐标系是否存在、名字是否百分百匹配,最好使用标准的EPSG代码(如32650);三、修正源头(导入脚本)或修补存量数据(用setSRS过程),最重要的是,一切操作先在测试库上验证通过再说。

ORA-13455报错搞不定,GeoRaster元数据TRS问题远程修复经验分享