【发布时间】:2017-11-14 01:29:43
【问题描述】:
我正在尝试将一个非常大的值 (>536MB) 设置到 cx_oracle CLOB 变量中,但它似乎在 512MB 标记附近失败。
conn = cx_Oracle.connect('foo/bar@baz')
cur = conn.cursor()
clob = cur.var(cx_Oracle.CLOB)
# The following is successful
clob.setvalue(0, 'A' * 1024 * 1024 * 511)
# The following fails
clob.setvalue(0, 'A' * 1024 * 1024 * 512)
第二个命令(或任何大于此的值)失败:
cx_Oracle.DatabaseError: ORA-03146: Invalid buffer length for TTC field
在对第二个命令进行了 3 次调用后,会话本身似乎已断开连接(而第一个命令不会发生这种情况)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cx_Oracle.OperationalError: ORA-03135: connection lost contact
Process ID: 17567
Session ID: 137 Serial number: 9226
我已经在两个环境中进行了测试,结果相同:本地环境中的 Python 连接到本地 Oracle;和 python 连接到不同的远程 Oracle 环境的远程 unix 环境。它们都在完全相同的1024 * 1024 * 512 行失败,这让我相信问题可能出在 cx_Oracle 上。
数据库版本:Oracle 12CR1
Oracle 客户端版本:12.1.0.2.0
cx_Oracle 版本:在 5.1.3 和 6.0.3 上测试,结果相同
Python 版本:2.7.13
一切都是 64 位的。
我的用例是我需要调用 PLSQL 过程将 CLOB 插入数据库。我们的项目遵循特定的 ERP 规则集,我们不允许直接进行 DML。我有类似于以下的代码:
data = get_user_provided_data()
conn = cx_Oracle.connect('foo/bar@baz')
cur = conn.cursor()
clob = cur.var(cx_Oracle.CLOB)
clob.setvalue(0, data)
cur.callproc('xxfoo_bar_pkg.insert_one',
keywordParameters={
'p_data_i': clob,
})
【问题讨论】:
-
你可能在这里遇到了一个错误,因为数据库连接不应该直接死掉,即
ORA-03135: connection lost contact。您能否也确认您的 Oracle 客户端版本(由 Python 驱动程序加载的库。 -
这将在github.com/oracle/python-cx_Oracle/issues/112 中跟进。一般来说,如果您通过 SQL 插入 LOB 列,请避免使用临时 LOB,以免使用临时表空间。他们也没有这个问题。
-
@gvenzl 我使用的是 12.1.0.2.0 Oracle 客户端版本
-
@ChristopherJones 我已经更新了问题的底部以包含我正在使用的代码示例。我们正在使用 PLSQL 过程来执行实际的插入(我们不允许从 python 直接创建 DML)。调用
cur.callproc时有没有办法避免临时 LOB?