跨线程共享的 django 连接导致 ora-01000 超出最大打开游标
Posted
技术标签:
【中文标题】跨线程共享的 django 连接导致 ora-01000 超出最大打开游标【英文标题】:django connections shared across threads causes ora-01000 maximum open cursors exeeded 【发布时间】:2013-11-14 10:37:10 【问题描述】:如果运行时间过长,我想停止执行 SQL 语句。
为了实现这一点,我破解了django.core.db.backends.oracle.base
。在FormatStylePlaceholderCursor.execute
和executemany
中,而不是:
return self.cursor.execute(TIMEOUT, query, self._param_generator(params))
我愿意:
return timelimited(TIMEOUT, self.cursor.execute, query, self._param_generator(params))
timelimited
是这个配方中的一个函数:http://code.activestate.com/recipes/576780-timeout-for-nearly-any-callable/。它在单独的线程中包装一个函数(即cursor.execute
)并等待TIMEOUT
。如果函数没有返回,则线程停止。
通过此修改,我正在运行的应用程序在一段时间后抛出 ora-01000 最大游标超出。我在徘徊为什么包装cursor.execute
会导致这个问题,如何解决它以及这个问题的其他可用解决方案。
【问题讨论】:
“被杀”是什么意思?你能控制杀戮过程吗?为什么需要超时? Oracle 在解析查询时会创建一个执行的“程序”。这一直存在于 Oracle 的内存中,直到查询关闭或数据库连接关闭。 this thread 可能会有所帮助 @Ivan - 我的意思是调用 thread.stop()。我需要超时,因为这将连接到缓存数据库。如果缓存数据库不可用或需要很长时间才能响应,我不会等待很长时间。我想取消执行并转至主数据库。 @alko - 这实际上没有帮助。请不要我试图保护连接中断的情况 - 在其他短查询的中间发生了一些事情,所以这需要在客户端处理。 顺便说一句,您使用的是什么 python(jython/cpython/pypy 和版本)? 【参考方案1】:我不熟悉 Django 和 Python。我可以告诉你 OCI 驱动程序为用户提供了什么。
您必须关闭查询句柄 - 或者它在 Python 中的名称。否则你会在数据库端泄漏资源 如果查询仍处于活动状态,您可以使用 OCIBreak 调用中断它。这个是线程安全的,可以从任何线程调用,无论后台线程对连接做什么 尝试检查一下,Oracle 的 Python 驱动程序是否允许您调用 OCIBreak 和 OCIResetThis 是您所需要的。 Connection.cancel()
【讨论】:
老实说,这不是我需要的东西。让我解释一下(只有四行代码,很抱歉在 cmets 中缺少格式): import cx_Oracle as db \n conn = db.connect(connect_string) \n #HERE UNPLUG YOUR ETHERNET CABLE \n conn.ping() # will永远挂起\n 好的,在这种情况下,您将面临 DCD(死连接检测)问题。有很多关于这个的文章,甲骨文也提出了一些建议。 “最佳”方法是将奇怪的子句(ENABLE=BROKEN)
放入 tnsnames.ora
条目中。这使得 Oracle 在网络连接上使用 TCPKeepAlive。您将需要root privs。调整几个与 TCPKeepAlive 相关的内核级参数。诀窍在于 DCD 在这种情况下由 Linux 内核处理 - 这种方法确实有效。
Connection.cancel()
中断数据库服务器端的“线程”执行。这可能是如何将连接返回到池中的最快方法。当然,这仅在您没有任何网络问题时才有效。以上是关于跨线程共享的 django 连接导致 ora-01000 超出最大打开游标的主要内容,如果未能解决你的问题,请参考以下文章