Oracle数据库升级对UTL_FILE的影响

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

8e3ada567bc155e3a5c9068daa4b178a.png

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

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

提示如下错误,

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

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

SQL> !oerr ora 29280
29280, 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中操作文件的目录路径,特意强调了所有的用户都可以读写这个参数定义的文件,

8e1a4aaa456c28e08a208b1429a59344.png

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目录对象,它可以提供更加弹性和细粒度的权限控制,而且支持动态调整,

500bf06732ded07e8fff0456b93a34f1.pnghttps://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/

f8cfcf652776af6f9085d0febe8728e5.png

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

fd6d787852fffebc8e152bd08b3cb8d4.png

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

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

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

Desupport of UTL_FILE_DIR Initialization Parameter
Starting 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 X
ORA-06512: 在 "SYS.UTL_FILE", line X
ORA-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知识还是有用的,至少能未雨绸缪,但这其实就对开发人员提高了要求,不能将数据库看做黑盒,还是得能有针对性地了解数据库,才能更好地运用数据库提供的特性,这算是相辅相成的道理。

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

2f98113b30707aece3762a13c93dbe3f.png

近期更新的文章:

MySQL架构中存储引擎的介绍

参加数据技术嘉年华大会有感

最近碰到的一些问题

MySQL的日期时间计算速查表

MySQL架构中SQL层和存储层的介绍

近期的热文:

推荐一篇Oracle RAC Cache Fusion的经典论文

"红警"游戏开源代码带给我们的震撼

文章分类和索引:

公众号1200篇文章分类和索引

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值