python-oracledb超时导致程序关闭

pdkcd3nj  于 2023-08-03  发布在  Oracle
关注(0)|答案(1)|浏览(123)

我有一个函数,它应该从数据库中检索DDL以及特定表的索引。大多数情况下,这个函数都能正常工作,但是对于一些特定的表,当调用这个函数时,我会超时。为了解决这个问题并避免程序陷入无限循环,我为连接添加了一个超时,现在程序在计时器超时后简单地关闭,而不是抛出异常。
所以这里似乎有两个问题。第一,当超时时程序的随机关闭应该引发异常,第二,为什么首先发生超时。
下面是相关函数的代码,为了简单起见,已经减少了:

def _get_ddl(dbconnection: oracledb.Connection, table: str, schema: str):
    dbconnection.call_timeout = 2000  # 2 seconds

    try:
        # Add semicolons as terminators for this session
        cursor = dbconnection.cursor()
        cursor.execute("BEGIN\n"
                       "    DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', true);\n"
                       "END;")
        # Query DDL
        cursor.execute(f"SELECT DBMS_METADATA.GET_DDL('TABLE', '{table}') AS DDL FROM DUAL")
        # Program breaks in the read() part here
        ddl = cursor.fetchone()[0].read()

        # Query indeces
        cursor = dbconnection.cursor()
        cursor.execute(f"SELECT DBMS_METADATA.GET_DDL('INDEX', index_name) FROM all_indexes WHERE table_name = '{table}' AND owner = '{schema.upper()}'")
        indeces = list(str(x[0]) for x in cursor.fetchall())

        # Parses the retreived ddl and indeces into custom type
        return utils.parse_ddl(ddl, indeces)
    except BaseException:
        # ... Cut for simplicity
        raise

字符串
被调用的函数在一个tkinter应用程序内运行,所以我有点恼火,程序只是在没有任何通知的情况下停止。此外,这个问题似乎并不是每个表都发生,而是只发生在某些表上。当我手动执行SQL时,我得到了预期的结果,而且当我手动添加断点和单步执行时,我在查询ddl时从未得到超时。仅当运行时不带断点。在execute()调用之间添加睡眠计时器也没有帮助。
有人觉得这很熟悉吗?或者也许有人知道如何进一步调试它?因为我已经没办法了。

vhmi4jdf

vhmi4jdf1#

经过几轮调试后,我发现在执行DDL请求后开始处理返回的LOB对象时,问题就发生了。在使用CLOB和BLOB数据的文档中,我发现:

# returns strings or bytes instead of a locator
oracledb.defaults.fetch_lobs = False

字符串
当在执行请求之前将此标志设置为false时,先前崩溃的表不再发生超时/崩溃。我仍然不确定为什么显式阅读CLOB数据会导致数据库超时并退出程序而没有任何异常,但这似乎至少解决了这个问题。

相关问题