超时时重新连接MySQL
我有一个Python程序,该程序在后台运行数周,偶尔执行一次数据库查询.为此,我使用的是ORM peewee
(2.2.1版).我正在使用MySQL
作为后端.
I have a Python program which runs on background for weeks, and does database queries every once in a while. For that, I am using the ORM peewee
(version 2.2.1). I am using MySQL
as a backend.
最近,通常在运行程序几天后,访问数据库时经常遇到问题. peewee
引发的错误是
Lately I've encountered a recurring problem with accessing the DB, usually after days of running the program. The error which is raised by peewee
is
peewee.OperationalError: (2006, 'MySQL server has gone away')
回溯深入到peewee
中.我将其发布在这里,但是由于我的virtualenv
使文件名过长,因此我将其缩短了:
The traceback is deep in peewee
. I post it here, but as my virtualenv
makes filenames too long, I am shortening them:
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
服务器执行ping操作,以使其保持活动状态(连接?).不过,我不确定如何通过ORM做到这一点. (我应该每小时简单地SELECT 1
吗?) - 在4个月前打开的此github peewee问题中,错误被提及,但是据称在那里已经解决了(并且我正在使用较新的版本).
- 在
trac
的 7岁的问题中,一个建议是增加MySQL
的超时时间为3天. - 在此论坛讨论中,建议增加
MySQL
的超时选项,但是提供了对MySQL JDBC连接器使用autoReconnect选项"的替代方法.我试图弄清楚Python的MySQLdb
模块是否存在这样的选项,但找不到. - 我找到了 MySQL参考页关于重新连接行为,但是对于我对
MySQL
的理解有些复杂(通常我只使用ORM),而且我不知道如何从peewee
中应用任何一个.
- In this question, one of the comments suggest pinging the
MySQL
server every once in a while to keep it (the connection?) alive. I am not sure how to do it via the ORM, though. (should I simplySELECT 1
every hour, say?) - In this github peewee issue, which was opened 4 months ago, the same error is referred, though, it is claimed there that it is solved (and I am using a newer version).
- In a 7 year old issue of
trac
, one suggestion is to increase the timeout ofMySQL
for 3 days. - In this forum discussion, the option of increasing
MySQL
's timeout is suggested, but an alternative of "using the autoReconnect option for the MySQL JDBC connector" is offered. I tried to figure out if such an option exists for Python'sMySQLdb
module, but couldn't find. - I have found this MySQL reference page on reconnection behaviour, but it's a bit complicated for my understanding of
MySQL
(usually I work only with ORMs), and I don't know how to apply any of it frompeewee
.
即使我能够对数据库执行ping操作以使连接保持更长的时间,但我认为在不需要连接时保持连接的活动仍然是一种不好的做法.有什么办法可以通过ORM重新打开连接吗?我认为ping和增加MySQL
的超时都是变通办法,而真正的解决方案是在需要时重新连接(而真正的解决方案是我要的).
Even if I'm able to ping the database to keep the connection alive for longer periods, I think it is considered a bad practice to keep a connection alive when one doesn't really need it. Is there any way to reopen the connection via the ORM? I consider both pinging and increasing the timeout of MySQL
as workarounds, while a real solution would be to reconnect when needed (and a real solution is what I'm asking for).
您必须捕获异常并根据哪个错误重新连接或执行其他操作.无论是连接超时,网络问题还是必须重新启动MySQL.
You have to catch the exception and based on which error, reconnect or to do something else. Whether it is a connection time out, or a network problem or the MySQL had to be restarted.
以下(伪)代码显示了如何执行此操作,但还有更多内容.您可能需要尝试几次,然后再纾困,或者也许每2分钟左右尝试一次.
The below (pseudoish) code shows how you could do that, but there is more to it. You'll want to try a few times and then bail out, or maybe try every 2 minutes or so.
while True:
try:
# do your database stuff
except peewee.OperationalError as exc:
# Oops! We have to try to reconnect
是否使用ORM并不重要.但是,ORM可能提供此功能.
Does not really matter whether you use an ORM or not. However, an ORM might offer this functionality.