我正在使用psycopg2连接到远程主机上的PostgreSQL数据库。我打开一个连接并等待请求,然后对于每个请求,我在连接上运行查询并返回数据。
但是当连接已经打开后网络连接丢失时,下一个数据库查询会挂起,我必须手动终止该程序。
细节:
我需要一些可靠的方法来在运行查询之前检测失败的连接,因此我的程序不会挂起,或者让cursor.execute(..)
在失败的连接上引发异常的方法。
import psycopg2
import time
conn = psycopg2.connect("host='dbs' dbname='foo' user='joe' password='x'")
time.sleep(10) # I manually turn VPN off during this sleep..
cu = conn.cursor()
cu.execute('SELECT 1') # <- hangs here
print cu.fetchone()
cu.commit()
import socket
socket.setdefaulttimeout(10)
psycopg.connection
的套接字上设置TCP超时:
..
conn = psycopg2.connect(...
s = socket.fromfd(conn.fileno(), socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
..
psycopg.connection
的套接字启用keepalive:
...
conn = psycopg2.connect(...
s = socket.fromfd(conn.fileno(), socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
...
看看套接字超时,在阅读this和this后,这些设置对我有用
s = socket.fromfd(connection.fileno(),
socket.AF_INET, socket.SOCK_STREAM)
# Enable sending of keep-alive messages
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Time the connection needs to remain idle before start sending
# keepalive probes
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, int(ceil(time)))
# Time between individual keepalive probes
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 1)
# The maximum number of keepalive probes should send before dropping
# the connection
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3)
为了确保连接仍然有效,请阅读属性connection.isolation_level
。如果连接已经死亡,这将用OperationalError
提高pgcode == "57P01"
。
try:
connection.isolation_level
except OperationalError as oe:
conn = psycopg2.connect(dsn)