cx_oracle之DPI-1054:connection cannot be closed when open statements or LOBs exist

背景

在flask项目中,将oracle数据表中有个字段从varchar2类型修改为clob之后,测试通过后,上线运行时发现有一个报错:

1
2
3
4
5
6
7
8
9
10
11
raised exception: DatabaseError(<cx_Oracle._Error object at 0x052B49C0>,)
Traceback (most recent call last):
File "d:\python\venv\hzinfo\lib\site-packages\celery\app\trace.py", line 218, in trace_task
R = retval = fun(*args, **kwargs)
File "d:\python\venv\hzinfo\lib\site-packages\celery\app\trace.py", line 396, in __protected_call__
return self.run(*args, **kwargs)
File "D:\hzinfoworkspace\hzinfo\app\firewall\fwPoolSync.py", line 106, in src_sync
src_before, src_dict = getSrcPoolBefore(departments)
File "D:\hzinfoworkspace\hzinfo\app\firewall\fwPoolSync.py", line 98, in getSrcPoolBefore
db.close()
DatabaseError: DPI-1054: connection cannot be closed when open statements or LOBs exist

排查

根据报错,可定位到cx_oracle的问题,导致db连接无法关闭。检查下测试环境和线上环境差异:

线上环境cx_oracle版本:6.0.2

测试环境cx_oracle版本:5.3

python版本均为:2.7.9

那么应该就是cx_oracle版本导致了,尝试直接更新到最新版本的cx_oracle:

1
2
3
4
5
6
7
pip install --upgrade cx_oracle

Installing collected packages: cx-oracle
Found existing installation: cx-Oracle 6.0.2
Uninstalling cx-Oracle-6.0.2:
Successfully uninstalled cx-Oracle-6.0.2
Successfully installed cx-oracle-7.1.3

直接更新到了7.1.3版本,再次运行就成功了。

总结

根据报错代码在github上查了下,果然有人提过issue。

作者答复说在6.2版本之前的确是存在这个问题的,有两种方法可以解决规避:

  • 在flask或者Django项目中也可以不要显性的调用db.close(),让系统自动关闭就可以了。
  • 更新cx_oracle版本到6.2及以上

更多内容可直接参考:

https://github.com/oracle/python-cx_Oracle/issues/138

对LOBs的介绍可参考:

https://docs.oracle.com/cd/B10501_01/appdev.920/a96591/adl01int.htm