在Oracle中,我如何取消断开的连接?

时间:2013-11-06 18:24:49

标签: python multithreading oracle cx-oracle oci

此代码在python中,但基本上它使用OCI所以应该可以用任何其他语言重现:

import cx_Oracle as db
dsn = '(DESCRIPTION =(CONNECT_TIMEOUT=3)(RETRY_COUNT=1)(TRANSPORT_CONNECT_TIMEOUT=3)(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = SOME_HOST)(PORT = 1531)))(CONNECT_DATA =(SERVICE_NAME = SOME_NAME)))'
connect_string = "LOGIN/PASSWORD@%s" % dsn
conn = db.connect(connect_string)
conn.ping() # WILL HANG FOREVER!!!

如果SOME_HOST失效,这将永远挂起!

它与OCIPing无关 - 如果我替换:

ping()

使用:

cursor = conn.cursor()
cursor.execute('SELECT 1 FROM DUAL') # HANG FOREVER AS WELL

这也会挂起。

我正在使用 SQL * Plus:2013年11月6日星期三12:17:09发布11.2.0.3.0版本

我尝试在线程中包装此代码并等待同时杀死线程,但这不起作用。这段代码自己创建一个线程,而python无法杀死它。你有什么想法如何恢复?

3 个答案:

答案 0 :(得分:0)

简短的回答是使用try / except / finally块,但如果部分代码真的在等待永远不会满足的条件,那么你需要做的是实现内部超时。有很多方法可以做到这一点。您可以根据需要调整solution to this problem以完成此任务。

希望这有帮助。

答案 1 :(得分:0)

我在中断conn.ping()时遇到了同样的问题。
现在,我使用下一个构造:

from threading import Timer

pingTimeout = 10 # sec

# ...

def breakConnection():
    conn.cancel()
    connection = False

try:
    t = Timer(pingTimeout, breakConnection)
    cursor = conn.cursor()
    cursor.execute('SELECT 1 FROM DUAL')
    t.close()
    cursor.close()
except Exception:
    connection = False

if not connection:
    print 'Trying to reconnect...'
    # ...

这是一种肮脏的方式,但是可以。

检查连接是否可用的真实方法是执行要运行的应用程序语句(我不是说SELECT 1 FROM DUAL)。 如果发现异常,请尝试重试。

答案 2 :(得分:-1)

如果你想要密切联系,请尝试

conn.close()