Does this thread-local Flask-SQLAchemy session cause a "MySQL server has gone away" error?
<p>I have a web application that runs long jobs that are independent of user sessions. To achieve this, I have an implementation for a thread-local Flask-SQLAlchemy session. The problem is a few times a day, I get a <code>MySQL server has gone away</code> error when I visit my site. The site always loads upon refresh. I think the issue is related to these thread-local sessions, but I'm not sure.</p>

<p>This is my implementation of a thread-local session scope:</p>

<pre><code>@contextmanager
def thread_local_session_scope():
    """Provides a transactional scope around a series of operations.
    Context is local to current thread.
    """
    # See this StackOverflow answer for details:
    # http://stackoverflow.com/a/18265238/1830334
    Session = scoped_session(session_factory)
    threaded_session = Session()
    try:
        yield threaded_session
        threaded_session.commit()
    except:
        threaded_session.rollback()
        raise
    finally:
        Session.remove()
</code></pre>

<p>And here is my standard Flask-SQLAlchemy session:</p>

<pre><code>@contextmanager
def session_scope():
    """Provides a transactional scope around a series of operations.
    Context is HTTP request thread using Flask-SQLAlchemy.
    """
    try:
        yield db.session
        db.session.commit()
    except Exception as e:
        print 'Rolling back database'
        print e
        db.session.rollback()
    # Flask-SQLAlchemy handles closing the session after the HTTP request.
</code></pre>

<p>Then I use both session context managers like this:</p>

<pre><code>def build_report(tag):
    report = _save_report(Report())
    thread = Thread(target=_build_report, args=(report.id,))
    thread.daemon = True
    thread.start()
    return report.id

# This executes in the main thread.
def _save_report(report):
    with session_scope() as session:
        session.add(report)
        session.commit()
        return report

# These executes in a separate thread.
def _build_report(report_id):
    with thread_local_session_scope() as session:
        report = do_some_stuff(report_id)
        session.merge(report)
</code></pre>

<p><strong>EDIT: Engine configurations</strong></p>

<pre><code>app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://&lt;username&gt;:&lt;password&gt;@&lt;server&gt;:3306/&lt;db&gt;?charset=utf8'
app.config['SQLALCHEMY_POOL_RECYCLE'] = 3600
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
</code></pre>