Psycopg2 db连接在丢失的网络连接上挂起
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Psycopg2 db连接在丢失的网络连接上挂起相关的知识,希望对你有一定的参考价值。
Problem description
我正在使用psycopg2连接到远程主机上的PostgreSQL数据库。我打开一个连接并等待请求,然后对于每个请求,我在连接上运行查询并返回数据。
但是当连接已经打开后网络连接丢失时,下一个数据库查询会挂起,我必须手动终止该程序。
细节:
- 它挂了至少2个小时(我等不了多久)
- “网络故障”情况实际上是VPN下降(数据库主机只能通过VPN访问)
- 我不能使用异步连接,因为我需要事务
- python 2.6
- psycopg 2.2.1
- debian linux 6和7,64bit
- postgresql 8.4和9.1
What I want/need
我需要一些可靠的方法来在运行查询之前检测失败的连接,因此我的程序不会挂起,或者让cursor.execute(..)
在失败的连接上引发异常的方法。
Example:
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()
What have I tried (and what didn't work):
- 设置TCP超时“全局” - 在psycopg2导入之前,我添加了:
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)
以上是关于Psycopg2 db连接在丢失的网络连接上挂起的主要内容,如果未能解决你的问题,请参考以下文章
如何在与 SQLAlchemy 和 psycopg2 的 PostgreSQL 连接上设置“lock_timeout”?
psycopg2 OperationalError:无效的连接选项