Python MariaDB连接池在一段时间后耗尽

Python MariaDB连接池在一段时间后耗尽,python,Python,我正在使用MariaDB Database Connector for Python,我有一个singleton数据库类,负责创建一个池并在该池上执行数据库操作。每次进入泳池后,我都会尽力关闭泳池。但是,尽管如此,过了一段时间,池变得不可用,并被卡住,永远无法释放。这可能是连接器的错误,也可能是代码中的错误。一旦池耗尽,我将创建并返回一个正常连接,这对于每一次数据库访问都是无效的 以下是我的数据库模块代码: import mariadb import configparser import

我正在使用MariaDB Database Connector for Python,我有一个singleton数据库类,负责创建一个池并在该池上执行数据库操作。每次进入泳池后,我都会尽力关闭泳池。但是,尽管如此,过了一段时间,池变得不可用,并被卡住,永远无法释放。这可能是连接器的错误,也可能是代码中的错误。一旦池耗尽,我将创建并返回一个正常连接,这对于每一次数据库访问都是无效的

以下是我的数据库模块代码:

import mariadb 

import configparser
import sys


from classes.logger import AppLogger

logger = AppLogger(__name__)

connections = 0

class Db:
    """
    Main database for the application
    """   
    
    config = configparser.ConfigParser()
    config.read('/app/config/conf.ini')
    db_config = db_config = config['db']
    try:
        conn_pool = mariadb.ConnectionPool( 
            user = db_config['user'],
            password = db_config['password'],
            host = db_config['host'],
            port = int(db_config['port']),
            pool_name = db_config['pool_name'],
            pool_size = int(db_config['pool_size']),
            database = db_config['database'],
        )
    except mariadb.PoolError as e:
        print(f'Error creating connection pool: {e}')
        logger.error(f'Error creating connection pool: {e}')
        sys.exit(1)


    def get_pool(self):
            return self.conn_pool if self.conn_pool != None else self.create_pool()
    def __get_connection__(self):
        """
        Returns a db connection
        """

        global connections
        try:
            pconn = self.conn_pool.get_connection()
            pconn.autocommit = True
            print(f"Receiving connection. Auto commit: {pconn.autocommit}")
            connections += 1
            print(f"New Connection. Open Connections: {connections}")
            logger.debug(f"New Connection. Open Connections: {connections}")
        except mariadb.PoolError as e:
            print(f"Error getting pool connection: {e}")
            logger.error(f'Error getting pool connection: {e}')
            # exit(1)
            pconn = self.ــcreate_connectionــ()
            pconn.autocommit = True
            connections += 1
            logger.debug(f'Created normal connection following failed pool access. Connections: {connections}')
        return pconn

        
    def ــcreate_connectionــ(self):
        """
        Creates a new connection. Use this when getting a
         pool connection fails
        """
        db_config = self.db_config
        return  mariadb.connect(
                user = db_config['user'],
                password = db_config['password'],
                host = db_config['host'],
                port = int(db_config['port']),
                database = db_config['database'],
            )

    def exec_sql(self, sql, values = None):
        global connections
        pconn = self.__get_connection__()
        try:        
            cur = pconn.cursor()
            print(f'Sql: {sql}')
            print(f'values: {values}')
            cur.execute(sql, values)
            # pconn.commit()
            # Is this a select operation?
            if sql.startswith('SELECT') or sql.startswith('Select') or sql.startswith('select'):
                result = cur.fetchall() #Return a result set for select operations
            else: 
                result = True
                
            pconn.close()
            connections -= 1
            print(f'connection closed: connections: {connections}')
            logger.debug(f'connection closed: connections: {connections}')
            # return True #Return true for insert, update, and delete operations 
            return result
        except mariadb.Error as e:
            print(f"Error performing database operations: {e}")
            # pconn.rollback()
            pconn.close()
            connections -=1
            print(f'connection closed: connections: {connections}')     
            return False

        
要在模块中使用该类,我将该类导入其中,并从该类实例化一个对象,然后对其运行sql查询:

db = Db()
users = db.exec_sql("SELECT * FROM users")

你知道为什么池在一段时间(可能是几天)后会耗尽,而且永远无法恢复吗?

可能是与mariadb不同的错误。有时会引发错误,并且连接从未关闭。我认为最好的做法是使用
finally
部分来保证连接始终关闭,如下所示:

pconn=None
尝试:
pconn=self.\uuuuu获取\u连接\uuuuuu()
# ...
除mariadb外。错误为e:
# ...
最后:
如果pconn:
尝试:
pconn.close()
除:
#这不是真的期望,但如果发生这种情况,它不应该改变
#无论在尝试中发生了什么,除了上面的部分。

可能是与mariadb不同的错误。有时会引发错误,并且连接从未关闭。我认为最好的做法是使用
finally
部分来保证连接始终关闭,如下所示:

pconn=None
尝试:
pconn=self.\uuuuu获取\u连接\uuuuuu()
# ...
除mariadb外。错误为e:
# ...
最后:
如果pconn:
尝试:
pconn.close()
除:
#这不是真的期望,但如果发生这种情况,它不应该改变
#无论在尝试中发生了什么,除了上面的部分。

谢谢你的提示。但是,我很确定这是池错误,因为我在日志中看到了它,但在此之前可能发生了一些错误。不管怎样,finally子句应该是有用的。finally部分将运行,无论是否发生异常。所以,连接总是关闭的,这不是我想要的。@codezombie,我不同意
close()
根据以下内容返回到池的连接:“使用池的线程通过获取连接并通过调用连接(或使用对象销毁时的默认关闭)将其返回到池”。抱歉,我的错误。我说的是连接()的主体。你说得对。exec_sql()中的连接最终必须关闭。谢谢提示。但是,我很确定这是池错误,因为我在日志中看到了它,但在此之前可能发生了一些错误。不管怎样,finally子句应该是有用的。finally部分将运行,无论是否发生异常。所以,连接总是关闭的,这不是我想要的。@codezombie,我不同意
close()
根据以下内容返回到池的连接:“使用池的线程通过获取连接并通过调用连接(或使用对象销毁时的默认关闭)将其返回到池”。抱歉,我的错误。我说的是连接()的主体。你说得对。exec_sql()中的连接最终必须关闭。