sqlalchemy mysql connections not closing on flask api

Question:

I have an API I have written in flask. It uses sqlalchemy to deal with a MySQL database. I don’t use flask-sqlalchemy, because I don’t like how the module forces you into a certain pattern for declaring the model.

I’m having a problem in which my database connections are not closing. The object representing the connection is going out of scope, so I assume it is being garbage collected. I also explicitly call close() on the session. Despite this, the connections stay open long after the API call has returned its response.

sqlsession.py: Here is the wrapper I am using for the session.

class SqlSession:
    def __init__(self, conn=Constants.Sql):
        self.db = SqlSession.createEngine(conn)

        Session = sessionmaker(bind=self.db)
        self.session = Session()
    @staticmethod
    def createEngine(conn):
        return create_engine(conn.URI.format(user=conn.USER, password=conn.PASS, host=conn.HOST, port=conn.PORT, database=conn.DATABASE, poolclass=NullPool))

    def close(self):
        self.session.close()

flaskroutes.py: Here is an example of the flask app instantiating and using the wrapper object. Note that it instantiates it in the beginning within the scope of the api call, then closes the session at the end, and presumably is garbage collected after the response is returned.

def commands(self, deviceId):
    sqlSession = SqlSession(self.sessionType) <---

    commandsQueued = getCommands()
    jsonCommands = []
    for command in commandsQueued:
     jsonCommand = command.returnJsonObject()
     jsonCommands.append(jsonCommand)
     sqlSession.session.delete(command)
    sqlSession.session.commit()
    resp = jsonify({'commands': jsonCommands})
    sqlSession.close() <---  
    resp.status_code = 200
    return resp

I would expect the connections to be cleared as soon as the HTTP response is made, but instead, the connections end up with the "SLEEP" state (when viewed in the MySQL command line interface ‘show processlist’).

Asked By: melchoir55

||

Answers:

I ended up using the advice from this SO post:
How to close sqlalchemy connection in MySQL

I strongly recommend reading that post to anyone having this problem. Basically, I added a dispose() call to the close method. Doing so causes the entire connection to be destroyed, while closing simply returns connections to an available pool (but leave them open).

def close(self):
    self.session.close()
    self.db.dispose()

This whole this was a bit confusing to me, but at least now I understand more about the connection pool.

Answered By: melchoir55