确保 psycopg2 数据库连接处于活动状态

问题描述 投票:0回答:5

我有一个Python应用程序,它打开一个数据库连接,可以在线挂起一个小时,但有时数据库服务器会重新启动,而Python仍然有连接,但它无法工作,并出现

OperationalError
异常。

所以我正在寻找任何可靠的方法来“ping”数据库并知道连接是否有效。我检查了 psycopg2 文档,但找不到类似的内容。当然,我可以发出一些简单的 SQL 语句,例如

SELECT 1
并捕获异常,但我希望有一个本机方法,例如 PHP pg_connection_status

谢谢。

python database connection psycopg2
5个回答
80
投票

这个问题确实很老了,但仍然会出现在 Google 搜索中,所以我认为了解

psycopg2.connection
实例现在有一个
closed
属性
很有价值,当连接打开时,该属性将是
0
,并且更大连接关闭时大于零。以下示例应演示:

import psycopg2
import subprocess

connection = psycopg2.connect(
    dbname=database,
    user=username,
    password=password,
    host=host,
    port=port
)

print connection.closed # 0

# restart the db externally
subprocess.check_call("sudo /etc/init.d/postgresql restart", shell=True)

# this query will fail because the db is no longer connected
try:
    cur = connection.cursor()
    cur.execute('SELECT 1')
except psycopg2.OperationalError:
    pass

print connection.closed # 2

29
投票

pg_connection_status
是使用PQstatus实现的。 psycopg 不公开该 API,因此检查不可用。 psycopg 调用 PQstatus 本身的唯一两个地方是建立新连接时和执行开始时。所以是的,您需要发出一个简单的 SQL 语句来查明连接是否仍然存在。


19
投票

connection.closed
并不反映服务器关闭/切断连接。它仅表示客户端使用
connection.close()

关闭了连接

为了确保连接仍然有效,请阅读属性

connection.isolation_level
。如果连接断开,这将引发 pgcode == "57P01" 的操作错误。

这会增加数据库往返的一点延迟,但应该比

SELECT 1
或类似的方法更可取。

import psycopg2
dsn = "dbname=postgres"
conn = psycopg2.connect(dsn)

# ... some time elapses, e.g. connection within a connection pool

try:
    connection.isolation_level
except OperationalError as oe:
    conn = psycopg2.connect(dsn)

c = conn.cursor()
c.execute("SELECT 1")

5
投票

如何检查连接是否关闭:

  • conn.close 如果关闭则为 1,否则为 0

  • 如果关闭,它不仅在查询上而且在上下文管理器中都会引发

    except psycopg2.InterfaceError as exc:
    with conn:
    足以引发。

  • 然后您需要重新建立连接。例如读出密码并放入

    .connect(..)


0
投票

解决连接维护问题的最终解决方案最好使用连接池来实现,然后连接池负责维护实时连接。

© www.soinside.com 2019 - 2024. All rights reserved.