1

需要一些帮助,因为我找不到任何解决 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)。我们正在设置 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{NLS_DATE_FORMAT}
    • 为了确保日期格式,我们另外更改了会话alter session set nls_date_format ...

好的,这也很好用。但前提是我们在控制台上建立新的连接。脚本找到了新的 TNS 位置,可以建立连接,并且通过游标从过程中获取数据也可以正常工作。所有 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 的问题?

我已经黔驴技穷了。也许全世界的任何人都有一个解决方案......请原谅我的英语:-)如果您需要进一步的解释,我会尝试更准确地定义它。

4

1 回答 1

0

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

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

于 2014-12-02T00:02:07.650 回答