即使在session.close()和pool_size = 5之后,SQLAlchemy仍将会话保持在“空闲”状态

时间:2018-04-21 01:17:52

标签: python postgresql sqlalchemy

我正在使用SQLAlchemy和psycopg2与PostgreSQL。当我使用idle查看pg_stat_activity表时,我的会话保持在SELECT * FROM pg_stat_activity状态。在几分钟的过程中,我将在“闲置”状态下达到15-20个会话。这些连接都是< 5分钟。

我的代码正在执行dbsession.commit()和dbsession.close(),我的pool_size是默认值5.当pool_size为5时,如何在数据库端打开15-20个会话?我怎样才能限制数量?

以下是我的dbsessions和create_engine函数。

def processor(self, ids):
    logger.debug("Starting database connection")
    dbmanager = DatabaseManager(self.db_config)
    dbsession = dbmanager.get_db_session()
    logger.debug("Database session successfully created")
    rows = dbsession.query(TableA, TableB)\
        .filter(and_(TableA.id.is_(None), TableA.id.in_([ids])))\
        .outerjoin(TableB)\
        .all()
    for index, row in enumerate(rows):
        //processing code
    logger.debug("Committing data to database")
    dbsession.commit()
    dbsession.close()

我的dbmanager类

from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
from sqlalchemy.orm import sessionmaker

class DatabaseManager(object):

    def __init__(self, configuration):

        self.config = configuration

    def get_database_connection_string(self):

        db_url = {'drivername': self.config["dialect"],
                  'username': self.config["username"],
                  'password': self.config["password"],
                  'host': self.config["host"],
                  'database': self.config["database"],
                  'port': 5432}
        return URL(**db_url)

    def create_db_engine(self):
        connection_url = self.get_database_connection_string()
        engine = create_engine(connection_url)
        return engine

    def create_db_session(self, dbengine):
        Session = sessionmaker()
        Session.configure(bind=dbengine)
        dbsession = Session()
        return dbsession

    def get_db_session(self):
        engine = self.create_db_engine()
        session = self.create_db_session(engine)
        return session

当我从pg_stat_activity运行select时,我会看到什么。

'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'
'Client','ClientRead','idle',,,'COMMIT','client backend'

1 个答案:

答案 0 :(得分:0)

我相信是因为您每次创建一个新的Engine时都会创建一个Session,而不是一次创建一个Engine并从中生成Session

这将导致所有会话通过一个proxied进入Engine

所以类应该看起来像这样

class DatabaseManager(object):

    def __init__(self, configuration):

        self.config = configuration
        self.engine = this.create_db_engine()

    def get_database_connection_string(self):

        db_url = {'drivername': self.config["dialect"], ....
        return URL(**db_url)

    def create_db_engine(self):
        connection_url = self.get_database_connection_string()          
        return create_engine(connection_url)

    def create_db_session(self):
        Session = sessionmaker()
        Session.configure(bind=self.engine)
        dbsession = Session()
        return dbsession

    def get_db_session(self):
        session = self.create_db_session()
        return session

我通常还会重复使用相同的事务(Session而不是每次都重新生成Session

class DatabaseManager(object):

    def __init__(self, configuration):
        ...
        self.session = None   // Added

    def get_db_session(self):
        if not self.session:
            self.session = self.create_db_session()

        return self.session

永远不要关闭它,因为我正在Apache模式下使用CGI ...