I have a Django app and a Tornado service running alongside on the same server. In the Tornado service, I'm using the Django ORM to access the MySQL database. The same database is used by the Django app.
Every page in our Django web app, when rendered on the client, establishes a persistent (WebSocket) connection to the Tornado service. That service uses the Django ORM to retrieve data and return it to the client.
The website is not heavily used, and sometimes several hours or even a day or two may pass between subsequent requests.
I'm getting the infamous '2006: MySQL has gone away' error in the Tornado service after the website has been idle for a while. I did some digging and it appears that the culprit is the connection being dropped by MySQL.
This is what baffles me, however: I'm using the same Django ORM that the Django app is using, and yet the Django app itself never fires this error. Moreover, my understanding is that the Django ORM reconnects automatically if this error occurs, which explains why I'm not seeing this error in the Django app. Why is it happening for me in Tornado, then?
As it stands now, the only way for me to bring my Tornado instance back to life is to restart the gunicorn process running it. After a restart, Tornado will work without hiccups until I leave it be for several hours.
I've read this: https://code.djangoproject.com/ticket/21597#comment:29 and some of the answers to the similar problems here on StackOverflow, but I don't think increasing timeout on MySQL solves the issue, it just makes it less likely to occur. (And anyway, my
from django.db import connection; connection.close()
if not hasattr(handler, '_session'):
engine = importlib.import_module(
session_key = handler.get_cookie(django.conf.settings.SESSION_COOKIE_NAME)
handler._session = engine.SessionStore(session_key)
# get_user needs a django request object, but only looks at the session
django_request = Dummy()
django_request.session = get_django_session(handler)
user = django.contrib.auth.get_user(django_request) # 2006: MySQL has gone away
Before and after each request (through the
request_finished signals), Django calls
close_old_connections(), which tests each connection and closes it if it's unusable. You can call this method before and after you do anything with the connection. This will not close connections that are still usable, so you won't have a new connection each time you do something in Tornado.