Psycopg/Postgres:连接随机挂起

3

我目前正在开发一个基于CherryPy的应用程序,并使用psycopg2进行开发。同时,我还使用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会关闭呢?

在.conf文件中,max_connections设置为100,因此我不认为这是原因。单个cherrypy工作器只有10个线程。

有人知道我应该先查找哪里吗?

3个回答

2
Psycopg2在每次事务(包括SELECT查询)后都需要提交或回滚,否则会将连接保持在“IDLE IN TRANSACTION”状态。这现在是文档中的一个警告:
警告:默认情况下,任何查询执行,包括简单的SELECT查询,都会启动一个事务:对于长时间运行的程序,如果没有采取进一步的操作,会话将保持“idle in transaction”状态,这是几个原因不希望发生的情况(锁被会话占用,表膨胀...)。对于长时间运行的脚本,请确保尽快终止事务或使用自动提交连接。

0

很难确切地看到您正在填充和访问cherrypy.thread_data的位置。我建议您调查psycopg2.pool.ThreadedConnectionPool,而不是尝试自己绑定一个连接到每个线程。


0
虽然我不知道为什么成功的SELECT查询会阻塞连接,但在每个不必与其他查询一起使用的查询后面都加上.commit()解决了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接