【问题标题】:Set database connection timeout in Python在 Python 中设置数据库连接超时
【发布时间】:2011-01-23 08:43:31
【问题描述】:

我正在创建一个需要访问数据库的 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 中所做的。

谢谢

【问题讨论】:

  • 嗨,我看到没有接受任何错误的答案,您是否找到任何其他解决方案?
  • 不,我无法完成这项工作。迄今为止建议的解决方案根本行不通。
  • 为什么conn.cancel() 不起作用?当您尝试 Dmitry 的解决方案时会发生什么?
  • 我还没有机会测试 Dmitry 的解决方案。 (从那以后我开始做其他事情。)如果其他人添加了他们已经测试过的评论,我可以接受这个解决方案。
  • Dmitry 的解决方案非常有效!超时后,我收到“ORA-01013:用户请求取消当前操作”。所以我会接受那个anwser

标签: python database oracle cx-oracle python-db-api


【解决方案1】:

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

这些行中的一些东西:

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

【讨论】:

  • 这很好用,谢谢!这就是我可以终止长时间运行的请求的方法。
  • 这可行,但如果有网络问题则不行。在这种情况下,取消在 10 分钟后返回 ORA-12152: TNS:unable to send break message。
【解决方案2】:

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

sqlnet.outbound_connect_timeout= value

还有选择:

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

【讨论】:

  • 我认为这是用于连接,而不是语句执行。
【解决方案3】:

您可以查看在 Oracle 中设置 PROFILEs 以在一定数量的 logical_reads_per_call 和/或 cpu_per_call 后终止查询

【讨论】:

    【解决方案4】:

    系统警报超时

    以下是如何使用操作系统超时来执行此操作。它是通用的,适用于 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!!
    

    【讨论】:

    • 当然,Oracle(在服务器上)不会被中断——你说你想“放弃长时间运行的查询”,这意味着你只是放弃等待响应。如果你真的想让 Oracle 停止运行查询——这完全是另一回事,而且不是那么容易——你必须在服务器上“终止会话”......
    • 我的意思是查询继续在客户端不间断地运行。
    • FWIW,我尝试在尝试 connect() 到数据库的 Django 应用程序的上下文中使用信号。 signal 抛出异常,抱怨只能在主线程上使用& Django 多线程处理请求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2011-06-07
    • 1970-01-01
    • 2016-01-05
    • 2013-01-12
    • 2017-04-21
    • 2022-12-11
    相关资源
    最近更新 更多