问题 在Python中设置数据库连接超时


我正在创建一个需要访问数据库的RESTful API。我正在使用Restish,Oracle和SQLAlchemy。但是,我会尝试尽可能地设置我的问题,而不考虑Restish或其他Web API。

我希望能够为执行查询的连接设置超时。这是为了确保放弃长时间运行的查询,并丢弃(或回收)连接。此查询超时可以是全局值,这意味着,我不需要为每个查询或连接创建更改它。

给出以下代码:

import cx_Oracle
import sqlalchemy.pool as pool

conn_pool = pool.manage(cx_Oracle)
conn = conn_pool.connect("username/p4ss@dbname")
conn.ping()

try:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM really_slow_query")
    print cursor.fetchone()
finally:
    cursor.close()

如何修改上面的代码来设置查询超时? 此超时是否也适用于连接创建?

这类似于java.sql.Statement的setQueryTimeout(int seconds)方法在Java中的作用。

谢谢


13002
2018-03-03 18:53


起源

嗨,我看到没有任何答案被接受你是否找到了其他任何解决方案? - Ib33X
不,我没能做到这一点。到目前为止建议的解决方案根本不起作用。 - oneself
为什么不呢 conn.cancel() 工作?当您尝试德米特里的解决方案时会发生什么? - alldayremix
我没有机会测试德米特里的解决方案。 (之后我转向其他事情。)如果其他人添加了他们已经测试过的评论,我可以接受这个解决方案。 - oneself
德米特里的解决方案就像一个魅力!超时后,我得到一个“ORA-01013:用户请求取消当前操作”。所以我会接受这个 - Fabian76


答案:


对于查询,您可以查看计时器和conn.cancel()调用。

这些方面的东西:

t = threading.Timer(timeout,conn.cancel)
t.start()
cursor = conn.cursor()
cursor.execute(query)
res =  cursor.fetchall()
t.cancel()

12
2018-06-04 17:54



这很好用,谢谢!这就是我如何杀死长期运行的请求。 - Emmanuel


在linux中看到/etc/oracle/sqlnet.ora,

sqlnet.outbound_connect_timeout= value

也有选择:

tcp.connect_timeout和sqlnet.expire_time,祝你好运!


3
2017-09-27 05:40



我认为这是为了连接,而不是语句执行。 - Glyph
这是一个有效的解决方案,试试吧;) - BetarU


你可以看一下设置 简介在Oracle中,在一定数量的logical_reads_per_call和/或cpu_per_call之后终止查询


0
2018-03-03 23:02





使用系统警报进行定时

以下是使用操作系统timout执行此操作的方法。它是通用的,适用于Oracle之外的其他东西。

import signal
class TimeoutExc(Exception):
    """this exception is raised when there's a timeout"""
    def __init__(self): Exception.__init__(self)
def alarmhandler(signame,frame):
    "sigalarm handler.  raises a Timeout exception"""
    raise TimeoutExc()

nsecs=5
signal.signal(signal.SIGALRM, alarmhandler)  # set the signal handler function
signal.alarm(nsecs)                          # in 5s, the process receives a SIGALRM
try:
    cx_Oracle.connect(blah blah)             # do your thing, connect, query, etc
    signal.alarm(0)                          # if successful, turn of alarm
except TimeoutExc:
    print "timed out!"                       # timed out!!

-3
2018-03-11 10:38



这似乎不起作用。 Oracle不会中断。 - oneself
当然,Oracle(在服务器上)不会被打断 - 你说你想“放弃长时间运行的查询”,这意味着你只是放弃等待响应。如果你想让Oracle停止运行查询 - 这是另外一件事,而不是那么容易 - 你必须在服务器上“杀死会话”...... - Nick Perkins
我想说的是查询继续在客户端上不间断地运行。 - oneself
FWIW,我试图在尝试连接()到数据库的Django应用程序的上下文中使用信号。 signal抛出一个异常,抱怨它只能用在主线程和Django多线程请求处理上。 - JL Peyret