在mod_perl下的DBD :: Oracle,Cursors和Environment

时间:2014-12-01 22:03:12

标签: apache perl environment-variables mod-perl2 dbd

需要一些帮助,因为我无法找到解决DBD :: Oracle问题的任何解决方案。

首先,这是目前的情况:

  • 我们在公司运行带有mod_perl 2.0.4的Apache2
    • Apache Web服务器设置了启动脚本,该脚本设置了一些环境变量(LD_LIBRARY_PATH,ORACLE_HOME,NLS_LANG)
    • 在httpd.conf中还有LD_LIBRARY_PATH和ORACLE_HOME的环境变量(通过SetEnv)
  • 我们通常使用带有驱动程序DBD :: Oracle的perl模块DBI连接到我们的主数据库
    • 在我们创建一个新的DBI实例之前,我们也设置了一些perl env变量(%ENV)。我们正在设置ORACLE_HOME和NLS_LANG。

到目前为止,这个工作正常。但现在我们正在扩展我们的系统并需要连接到远程数据库。我们再次使用DBI和DBD :: Oracle。但是现在有一些新的条件:

  • 新连接必须与现有连接并行运行
  • 新连接的TNSNAMES.ORA位于不同的位置(不在$ ORACLE_HOME。'/ network / admin')
  • 新的数据库内容由存储过程提供,我们使用DBD :: Oracle和游标获取(如此处所述:https://metacpan.org/pod/DBD::Oracle#Binding-Cursors
  • 存储过程返回对象类型和集合类型,包含oracle类型DATE的属性
    • 要以可读格式获取这些日期,我们设置一个新的env变量$ ENV {NLS_DATE_FORMAT}
    • 为了确保日期格式,我们还通过alter session set nls_date_format ...
    • 更改会话

好的,这也很好。但只有我们在控制台上建立新连接。脚本可以找到新的TNS位置,可以建立连接,并且通过游标从过程中获取数据也可以正常工作。 Alle DATE类型按指定格式进行格式化。

现在,如果我们尝试在apache环境中建立此连接,则会失败。起初,DBI / DBD :: Oracle无法解析数据源名称。我认为这是因为我们新的TNSNAMES.ORA文件,或者更确切地说,DBI / DBD :: Oracle在Apache上下文中找不到该位置(由$ ENV {TNS_ADMIN}发布)。但我不知道为什么???

第二个问题是(如果我为第一个创建了一个脏的解决方法),$ ENV {NLS_DATE_FORMAT}发布的日期格式仅适用于我们光标选择的第一级。

BEGIN OPEN :cursor FOR SELECT * FROM TABLE(stored_procedure) END;

上面的示例返回包含日期属性的对象的集合类型。在Apache上下文中,无法识别NLS_DATE_FORMAT发布的格式。如果我使用像这样的简单形式

BEGIN OPEN :cursor FOR SELECT SYSDATE FROM TABLE(stored_procedure) END;

结果(单个日期字段)格式正确。所以我认为从属结构没有格式化,因为$ ENV {NLS_DATE_FORMAT}也只能在控制台上下文中工作,而不能在Apache上下文中工作。

因此,在Apache和mod_perl下运行的perl环境变量(%ENV)一定存在问题。也许是mod_perl的问题?

我在我的智慧结束。也许整个世界上的任何人都有解决方案...并原谅我的英语:-)如果你需要进一步的解释,我会尝试更精确地定义它。

1 个答案:

答案 0 :(得分:0)

如果您的问题是在处理请求时对%ENV所做的更改似乎没有得到遵守,这是因为mod_perl假设您可能正在运行多个线程,并且在更改%ENV时实际上并未更改过程环境,因此外部库(如oracle客户端)或子进程看不到更改。

首先使用prefork MPM可以解决这个问题,因此没有任何线程问题,然后使用Env::C而不是%ENV哈希值对环境进行更改。