cx_Oracle 中的 Python 长时间空闲连接获取:DPI-1080:连接已被 ORA-3113 关闭

Avn*_*hen 2 python oracle networking cx-oracle

我正在运行长时间运行的 Python 可执行文件。启动时使用 cx_Oracle 打开 Oracle 连接。空闲连接超过 45-60 分钟后 - 出现此错误。cx_Oracle 需要任何想法或特殊设置吗?

Chr*_*nes 5

不要在应用程序中保留未使用的连接,而是考虑在不需要时将其关闭,然后在需要时重新打开。建议使用连接池,因为池可以处理一些底层故障(例如您的故障),并为您提供可用的连接。

\n

在应用程序初始化时启动池一次:

\n
pool = cx_Oracle.SessionPool(user="username", password=pw, \n                  dsn="localhost/orclpdb1", min=0, max=4, increment=1)\n
Run Code Online (Sandbox Code Playgroud)\n

然后稍后获取连接并仅在需要时保持它:

\n
with pool.acquire() as connection:\n    cursor = connection.cursor()\n    for result in cursor.execute(\n             """select sys_context(\'userenv\',\'sid\') from dual"""):\n        print(result)\n
Run Code Online (Sandbox Code Playgroud)\n

块结束时with会将连接释放回池中。它\n不会被关闭。下次acquire()调用池时可以检查连接是否仍然可用。如果不是,它会给你一个新的。由于这些检查,即使您只有一个连接,该池也很有用。

\n

请参阅我的博客文章始终使用连接池 \xe2\x80\x94 和\n如何\n其中大部分适用于 cx_Oracle。

\n

但如果您不想更改代码,请尝试设置 Oracle 网络参数,EXPIRE_TIMEcx_Oracle 文档python-oracledb 文档中所示。这可以在不同的地方设置。在基于 C 的 Oracle 客户端(例如 cx_Oracle 和python-oracledb的厚模式)中:

\n
    \n
  • 对于 18c 客户端库,可以将其添加(EXPIRE_TIME=n)到连接描述符的描述部分
  • \n
  • 借助 19c 客户端库,还可以通过 Easy Connect 使用它host/service?expire_time=n
  • \n
  • 通过 21c 客户端库,它还可以在客户端 sqlnet.ora 文件中使用
  • \n
\n

如果 EXPIRE_TIME 用于防止防火墙终止空闲\n连接,则该值应略小于防火墙超时时间的一半。

\n

使用 python-oracledb 的精简模式,您可以expire_time在创建连接或池时传递参数,例如:

\n
pool = oracledb.create_pool(user="username", password=pw, \n                            dsn="dbhost.example.com/orclpdb",\n                            min=0, max=4, increment=1\n                            expire_time=4)\n
Run Code Online (Sandbox Code Playgroud)\n

这可能并不总是有帮助,具体取决于关闭连接的原因。

\n

从根本上讲,您应该/可以修复根本原因,这可能是防火墙超时、DBA 强加的用户资源或数据库空闲时间限制。

\n