ASGI, "MySQL server has gone away" and CONN_MAX_AGE

I have an ASGI Django (v3.1) application and MariaDB.
The problem is: DB drops idle connection after wait_timeout and after I open a page I get an exception:
MySQLdb._exceptions.OperationalError: (2006, 'MySQL server has gone away')
with following:
django.db.utils.OperationalError: (2006, 'MySQL server has gone away')
wait_timeout is default 28800
I set CONN_MAX_AGE=600, but it didn’t help.
What can be a root cause? How to fix?

Doesn’t anyone have an idea? :upside_down_face:

Ideas? Sure. Helpful ideas? Not-so-much :wink:

A brief review of the settings docs show a number of other possible settings that might be affecting this - possibly related to whether or not Django is opening the connection as an “interactive” session vs a “batch” session.

See things like:

Depending upon how busy you’re expecting your site to be, and whether or not your database is on the same server as your applications, you could also try:

  • setting CONN_MAX_AGE=0
  • changing your connection from using a TCP socket to a unix socket
  • setting CONN_MAX_AGE to something like 240. (Some of those settings above have defaults of 300 - if you set CONN_MAX_AGE to something less than that, you might be able to determine whether or not it’s one of those settings.)

Sorry - I know this isn’t much help, but maybe it’ll give you some ideas for further research. (I haven’t used MariaDB in more than 6 years.)

Ken

Thanks for the answer.
But the problem still present. I tried to set even CONN_MAX_AGE=5 :laughing: , but it looks as if Django doesn’t use this parameter at all.
Unfortunatelly, I can’t try WSGI - my application won’t work this way I think. But may be I add some stubs… Who knows) Or maybe it’s reasonable to write a simple WSGI app, just for DB tests…
And I can’t switch to unix socket - DB is on another host.

I solved the problem! :smile:

The root cause:
At the moment (version 3.1) Django ORM is syncronous and asgiref.sync.sync_to_async adapter is used. And here is the problem place.
This works always (for a some reason):
await sync_to_async(User.objects.all)()

And this works only for the first call and until DB closes the connection:
await sync_to_async(User.objects.get)(username=username)

Right after the connection is closed by DB such call leads to exception. Perhaps, this adapter keeps the connection open forever :laughing:

The easiest solution (from my point):
Take this code from Django channells:

And just use it instead of sync_to_async:
await database_sync_to_async(User.objects.get)(username=username)

I hope this might be useful for someone who’s come across with such issue as I did.

And of course this all will be deprecated when Djago becomes fully async. Someday… :stuck_out_tongue_winking_eye:

1 Like