3

我将 psycopg2 用于我目前正在开发的cherrypy 应用程序,并使用 cli & phpgadmin 手动处理一些操作。这是python代码:

#One connection per thread
cherrypy.thread_data.pgconn = psycopg2.connect("...") 
...
#Later, an object is created by a thread :
class dbobj(object):
 def __init__(self):
  self.connection=cherrypy.thread_data.pgconn
  self.curs=self.connection.cursor(cursor_factory=psycopg2.extras.DictCursor)
...
#Then,
try:
 blabla
 self.curs.execute(...)
 self.connection.commit()
except:
 self.connection.rollback()
 lalala
...
#Finally, the destructor is called :
def __del__(self):
 self.curs.close()

我在使用 psycopg 或 postgres 时遇到问题(尽管我认为后者更有可能)。在发送了一些查询之后,我的连接就死了。同样, phpgadmin - 通常- 也会被删除;它提示我在多次提出请求后重新连接。只有 CLI 保持不变。

问题是,这些都是随机发生的,我什至无法找出原因。我可以在几个页面请求后被锁定,或者在请求数百个页面后从未真正遇到任何事情。终止应用程序后,我在 postgres 日志中发现的唯一错误是:

...
LOG:  unexpected EOF on client connection
LOG:  could not send data to client: Broken pipe
LOG:  unexpected EOF on client connection
...

每次创建新的 dbobj 实例时,我都想创建一个新连接,但我绝对不想这样做。

另外,我读到除非所有事务都已提交,否则可能会遇到类似问题:我对每个 INSERT/UPDATE 查询都使用 try/except 块,但我从不将它用于 SELECT 查询,也不想写更多样板代码(顺便说一句,它们是否需要提交?)。即使是这样,为什么 phpgadmin 会关闭?

max_connections 在 .conf 文件中设置为 100,所以我认为这也不是原因。一个cherrypy worker只有10个线程。

有谁知道我应该先看哪里?

4

3 回答 3

2

Psycopg2 需要在每个事务(包括 SELECT 查询)之后提交或回滚,否则它会留下连接“IDLE IN TRANSACTION”。这现在是文档中的警告:

警告:默认情况下,任何查询执行,包括一个简单的 SELECT 都会启动一个事务:对于长时间运行的程序,如果不采取进一步的行动,会话将保持“在事务中空闲”,这是一种不受欢迎的情况,原因有很多(锁是举行的会议,表格膨胀......)。对于长期存在的脚本,要么确保尽快终止事务,要么使用自动提交连接。
于 2016-10-19T22:23:00.277 回答
0

很难确切地看到您在哪里填充和访问cherrypy.thread_data. 我建议您进行调查psycopg2.pool.ThreadedConnectionPool,而不是尝试自己将一个 conn 绑定到每个线程。

于 2010-11-14T04:42:18.673 回答
0

即使我不知道为什么成功SELECT的查询会阻塞连接,但.commit()在几乎每一个不必与另一个查询结合使用的查询之后都会溢出来解决问题。

于 2010-11-17T14:12:27.270 回答