我有一个Python程序,它在后台运行数周,并且每隔一段时间就进行一次数据库查询。为此,我使用ORM peewee
(版本2.2.1)。我使用MySQL
作为后端。
最近,我经常在运行程序几天后遇到了访问数据库的问题。 peewee
引发的错误是
peewee.OperationalError: (2006, 'MySQL server has gone away')
追溯深入peewee
。我在这里发布,但由于我的virtualenv
使文件名太长,我缩短了它们:
File ".../local/lib/python2.7/site-packages/peewee.py", line 2910, in save
ret_pk = self.insert(**field_dict).execute()
File ".../local/lib/python2.7/site-packages/peewee.py", line 2068, in execute
return self.database.last_insert_id(self._execute(), self.model_class)
File ".../local/lib/python2.7/site-packages/peewee.py", line 1698, in _execute
return self.database.execute_sql(sql, params, self.require_commit)
File ".../local/lib/python2.7/site-packages/peewee.py", line 2232, in execute_sql
self.commit()
File ".../local/lib/python2.7/site-packages/peewee.py", line 2104, in __exit__
reraise(new_type, new_type(*exc_value.args), traceback)
File ".../local/lib/python2.7/site-packages/peewee.py", line 2223, in execute_sql
res = cursor.execute(sql, params or ())
File ".../local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File ".../local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
peewee.OperationalError: (2006, 'MySQL server has gone away')
我发现可能的解决方案:
MySQL
服务器以保持它(连接?)活着。不过,我不知道如何通过ORM来做到这一点。 (我应该每小时SELECT 1
,比方说?)trac
MySQL
中,有一项建议是将MySQL
的超时时间延长3天。MySQLdb
超时的选项,但是使用mysql JDBC连接器的自动重新连接选项""提供。我试图弄清楚Python MySQL
模块是否存在这样的选项,但无法找到。peewee
的理解有点复杂(通常我只与ORM合作),我不知道如何应用MySQL
。即使我能够ping数据库以保持连接存活更长时间,我认为当一个人并不真正需要时保持连接是一种不好的做法。有没有办法通过ORM重新打开连接?我认为ping和增加{{1}}的超时作为解决方法,而真正的解决方案是在需要时重新连接(真正的解决方案是我要求的)。
答案 0 :(得分:8)
我有同样的问题,对于使用MySQLdb的peewee,我在初始化MySQL数据库实例时得到了以下解决方案:
db = MySQLDatabase(db_name, user=db_username, passwd=db_password, host=db_host, port=db_port)
db.get_conn().ping(True)
ping函数的位置有:
检查与服务器的连接是否正常。如果它 已经下降,尝试自动重新连接。
此功能可供长时间闲置的客户端使用 同时,检查服务器是否已关闭连接 并在必要时重新连接。
1.2.2中的新功能:接受可选的重新连接参数。如果是,那么 客户端将尝试重新连接。请注意,此设置为 执着。默认情况下,这在MySQL< 5.0.3中开启,之后关闭。
非标。您应该假设ping()执行隐式 回滚;仅在开始新交易时使用。你去过 警告。
db.get_conn().ping.__doc__
中的。请注意,如果再次创建另一个连接,则必须使用db.get_conn().ping(True)
。因此,如果您重新连接(例如通过db.connect()
),则必须重复ping。
答案 1 :(得分:5)
您必须捕获异常并根据哪个错误重新连接或执行其他操作。无论是连接超时,还是网络问题,还是必须重新启动MySQL。
以下(伪)代码显示了如何做到这一点,但还有更多。你想尝试几次然后拯救,或者每2分钟左右尝试一次。
while True:
try:
# do your database stuff
except peewee.OperationalError as exc:
# Oops! We have to try to reconnect
您是否使用ORM并不重要。但是,ORM可能会提供此功能。
答案 2 :(得分:0)
我已经解决了这个问题。
我的解决方案是使用PooledMySQLDatabase
模块中的mysql连接池playhouse.pool
。
请阅读:https://github.com/coleifer/peewee/issues/239
from peewee import *
from playhouse.pool import *