title: Why am I getting the "MySQL server has gone away" exception in Django?
body: <p>I'm working with Django 2.2.6.</p>
  
  <p>The same system that runs my django project also has a background service running, listening on a unix socket for requests. In Django Admin, if a user hits a button, Django sends a request on the unix socket, and the background service does something.</p>
  
  <p>My background service has full access to Django's ORM. It imports models from my project's models.py, and can query the database without any issues.</p>
  
  <p>The problem is that if I leave my django, and my background service running overnight, login to Django Admin, and hit the button, my background service throws an exception:</p>
  
  <pre><code>django.db.utils.OperationalError: (2006, 'MySQL server has gone away')
  </code></pre>
  
  <p>It appears that this is because the MySQL database has a timeout period, called <code>wait_timeout</code>. If a connection to the database isn't active for that long, MySQL will disconnect it. Unfortunately, Django doesn't notice, and tries to use it, throwing the error.</p>
  
  <p>Fortunately, Django has its own built-in CONN_MAX_AGE variable for each database defined in settings.py. If a database connection is older than the CONN_MAX_AGE, it shuts it down before a request and starts up a new one.</p>
  
  <p>Looking at my MySQL database:</p>
  
  <pre><code>&gt; show session variables where variable_name = "wait_timeout";
  +---------------+-------+
  | Variable_name | Value |
  +---------------+-------+
  | wait_timeout  | 28800 |
  +---------------+-------+
  </code></pre>
  
  <p>Looking at my Django's CONN_MAX_AGE variable:</p>
  
  <pre><code># ./manage.py shell
  &gt;&gt;&gt; from django.conf import settings
  &gt;&gt;&gt; settings.DATABASES['default']['CONN_MAX_AGE']
  0
  </code></pre>
  
  <p>Note: the 'default' database is the only one I have defined in my settings.py</p>
  
  <p>Also note that both my MySQL wait_timeout, and my Django's CONN_MAX_AGE are default values - I haven't changed them.</p>
  
  <p>According to the Django docs <a href="https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-CONN_MAX_AGE" rel="noreferrer">here</a>, a CONN_MAX_AGE value of 0 means: </p>
  
  <blockquote>
    <p>close database connections at the end of each request</p>
  </blockquote>
  
  <p>If django is meant to close the database connection after every request, why than am I running into this error? Why isn't it closing old connections the second I'm done running my query, and starting a new connection when I do a new query, hours later?</p>
  
  <p>Edit:</p>
  
  <p>Right now, my solution is to have my background service do a heartbeat. Once per hour seems to work fine. The heartbeat is just a simple, low-resource-consumption MySQL command like MyDjangoModel.objects.exists(). As long as it does a MySQL query to refresh the MySQL timeout, it works. Having this does add some complexity to my background service, as in one case, my otherwise single-threaded background service needed a background thread whose only job was to do heartbeats.</p>
  
  <p>If there's a simpler solution to this, or at least an explanation for why this happens, I'd like to hear it.</p>