Oracle数据库升级对UTL_FILE的影响

最近有个朋友提了一个问题,她们有套11g的数据库升级到19c,但是某个脚本中使用了utl_file进行文件操作,在11g中设置了UTL_FILE_DIR参数,而19c中没这个参数了,如果强制设置,就提示该参数obsolete,废弃了,

图片

相应地,脚本中这段逻辑,

UTL_FILE.FOPEN('/home/oracle/', 'test.txt', 'w');

提示如下错误

SQL 错误 [29280] [99999]: ORA-29280: 无效的目录对象ORA-06512: 在 "SYS.UTL_FILE", line XORA-06512: 在 "SYS.UTL_FILE", line XORA-06512: 在 line X

ORA-29280错误的解释,这是无效的directory对象名称,说的就是FOPEN函数的第一个参数值”/home/oracle/”,

SQL> !oerr ora 2928029280, 00000, "invalid directory object"// *Cause:  A corresponding directory object does not exist.// *Action: Correct the directory object parameter, or create a corresponding//          directory object with the CREATE DIRECTORY command.

我们通过官方文档可以找到一些线索,11g的《Reference》说UTL_FILE_DIR的意思是可以设置PL/SQL中操作文件的目录路径,特意强调了所有的用户都可以读写这个参数定义的文件,

图片

UTL_FILE包的使用可参见《Oracle数据导出新选择》,但是当时确实没太注意到UTL_FILE.FOPEN函数的第一个参数值,

UTL_FILE.FOPEN('UTL_FILE_DIR', 'test.txt', 'w');

从11g的文档,我们可以看到,UTL_FILE的作用就是提供客户端和服务端文件访问的权限,能访问的目录范围就是UTL_FILE_DIR参数给定义的,但是通过参数控制可访问的目录,存在安全隐患,一个是参数和用户本身其实并没有强关联,只要定义了,任何用户都能用,另外这个参数是个静态参数,修改生效,需要重启数据库,因此,不推荐使用UTL_FILE_DIR,而是推荐使用Oracle的directory目录对象,它可以提供更加弹性和细粒度的权限控制,而且支持动态调整,

https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm#ARPLS069

Connor McDonald曾写过这篇文章,提到了让UTL_FILE使用directory对象可以提升安全性的一些原因,有兴趣的朋友,可以了解下,https://connor-mcdonald.com/2018/06/27/utl_file_dir-and-18c/

图片

FOPEN函数的第一个参数官方解释是location,文件目录的位置,11g中要求是个directory对象,并且必须是大写,同时要求必须给执行FOPEN的用户对这个目录对象的读权限,

图片

因此,11g中支持这种跟着操作系统文件路径的逻辑,

UTL_FILE.FOPEN('/home/oracle/', 'test.txt', 'w');

但是,从18c开始,UTL_FILE_DIR参数就给废弃了,取而代之的是推荐设置directory对象名称,

Desupport of UTL_FILE_DIR Initialization ParameterStarting in Oracle Database 18c, the UTL_FILE_DIR parameter is no longer supported. Instead, specify the name of a directory object.
https://docs.oracle.com/en/database/oracle/oracle-database/18/upgrd/initialization-parameter-changes-oracle-database-18c.html#GUID-9455629C-9DA3-499B-AB06-02F98C2C6442

因此,正确使用UTL_FILE,第一步就是创建目录对象,并进行授权,

create directory test_dir as '/home/oracle';grant read, write on directory test_dir to bisal;

如果要模拟测试,可以用这段PL/SQL,

declare  f utl_file.file_type;begin  f := utl_file.fopen('/home/oracle','od.csv','W');  utl_file.fclose_all;end;/

执行会提示

SQL 错误 [29280] [99999]: ORA-29280: 无效的目录对象ORA-06512: 在 "SYS.UTL_FILE", line XORA-06512: 在 "SYS.UTL_FILE", line XORA-06512: 在 line X

如果改成directory对象名称作为第一个参数,就可以正常执行,

declare  f utl_file.file_type;begin  f := utl_file.fopen('TEST_DIR','od.csv','W');  utl_file.fclose_all;end;/

因此,针对从11g升级到19c,并且使用”/home/oracle”这种操作系统路径作为FOPEN参数的脚本逻辑,就得进行改造,换成directory对象名称,才可以正常执行。

这种废弃参数的场景,一般情况下,Oracle会在前几个版本中就会提到,但是不会明确这个参数具体会在什么版本真正废弃,给了你改造缓冲,因此了解一些和你的应用逻辑相关的Oracle知识还是有用的,至少能未雨绸缪,但这其实就对开发人员提高了要求,不能将数据库看做黑盒,还是得能有针对性地了解数据库,才能更好地运用数据库提供的特性,这算是相辅相成的道理。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/136449.html

联系我们
联系我们
分享本页
返回顶部