暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle数据库升级对UTL_FILE的影响

998

最近有个朋友提了一个问题,她们有套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 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中操作文件的目录路径,特意强调了所有的用户都可以读写这个参数定义的文件,

        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 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,




                      近期更新的文章:
                      MySQL架构中存储引擎的介绍
                      参加数据技术嘉年华大会有感
                      最近碰到的一些问题
                      MySQL的日期时间计算速查表
                      MySQL架构中SQL层和存储层的介绍

                      近期的热文:
                      推荐一篇Oracle RAC Cache Fusion的经典论文
                      "红警"游戏开源代码带给我们的震撼

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

                      文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论