如何跟踪cx_Oracle尝试连接数据库的方式?

时间:2018-07-03 21:59:07

标签: python conda cx-oracle

我有三个安装了cx_Oracle和Oracle Instantclient的Python Anaconda环境。我正在使用conda提供似乎运行良好的虚拟环境,并且正在使用Oracle Wallet向系统提供实际的凭证。请注意,这些环境不会并且永远不会安装SQL * Plus,因为它们仅是为了通过更高的抽象度(例如Python或Java)与数据库进行通信。

我遇到的麻烦来自三种环境中的两种。执行以下Python脚本时,连接仅可在三种环境之一中正常工作。请注意,标识符在各个环境中都不同,但大致相同。

import cx_Oracle
import os
os.environ['TNS_ADMIN'] = '/data/config/wallets/app'
conn = cx_Oracle.connect('/@ENV_CONNECTION')

当我在一个环境中执行此操作时,会得到一个预期的游标实例,并且一切正常。在另外两个上,我看到了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cx_Oracle.DatabaseError: ORA-12162: TNS:net service name is incorrectly specified

我已经 个五元组检查了 ,服务名称和钱包本身。有一个Java应用程序也在使用此钱包,如果该钱包被认为是坏的,它将无法连接,因此原则上不予考虑。

唯一剩下的未知数是如何引用钱包本身。

我如何反思cx_Oracle如何引用我的TNS_ADMIN位置并提取正确的目录?我觉得如果我能弄清楚,其余的我就能解决。

我所处环境的条件:

  • conda 4.4.11
  • 即时客户端12.2
  • cx_Oracle版本6.3.1

2 个答案:

答案 0 :(得分:1)

  • 检查cx_Oracle传递给较低层(例如Oracle Net)的最简单方法可能是扩展Connection类并添加您自己的日志记录。基类为cx_Oracle.Connection,请参见示例https://github.com/oracle/python-cx_Oracle/blob/master/samples/Subclassing.py

  • 您可以运行strace或类似工具来查看正在打开哪些Oracle配置文件(例如tnsnames.ora)。

  • 可以启用Oracle Net跟踪,请参见ADR Diagnostic Parameters in sqlnet.ora。为了进行简单的跟踪,我通常创建一个文件“〜/ .sqlnet.ora”,其内容如下: TRACE_LEVEL_CLIENT = USER ADR_BASE=/tmp 然后运行该应用程序,并在创建的/tmp/oradiag_*目录中深入到*.trc文件。

答案 1 :(得分:0)

克里斯托弗·琼斯(Christopher Jones)的回答使我获得了救赎,但现实情况是问题远不止于此。

我结束了在两台计算机的主目录中创建sqlnet.ora文件的工作-一台可以工作,另一台不能工作。我注意到了日志文件的显着差异。

“好”框有以下条目:

2018-07-06 09:59:36.726 : nnftrne:Using tnsnames.ora address (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521)) (CONNECT_DATA = (SID = my_sid))) for name ENV_CONNECTION

“错误”框中输入以下内容:

2018-07-06 10:02:12.879 : nnftrne:Using tnsnames.ora address (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521 for name ENV_CONNECTION

这个伤口转化为我曾经遇到过的最愚蠢,最令人惊讶的空白限制。

请记住,Java中也使用了所使用的钱包(及其对应的tnsnames.ora文件)。我的假设是,从共享资源中读取Python和Java时,它们的行为类似,因为它们会在必要时忽略换行符和空格。

我显然是错的。

“好”框中的条目如下所示:

ENV_CONNECTION =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521))
    (CONNECT_DATA =
      (SID = my_sid)
    )
  )

“错误”框中的条目如下所示:

ENV_CONNECTION =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521
  ))
    (CONNECT_DATA =
      (SID = my_sid)
    )
  )

差异足够细微,但对于Python来说是显而易见的:如果tnsnames.ora文件的格式不正确,则cx_Oracle将失败进行解析,而Java是 fine 与此。

感觉上像是一个错误,但修复格式后允许Python重新连接。