当前位置: 首页 > 知识库问答 >
问题:

python - sqlalchemy 数据库连接无法关闭?

周云
2024-07-12

刚才发现每次调用完接口都有一堆连接没关掉( 如下图 ):

image.png

于是写了一段本地代码无限循环跑发现单独执行一次是可以立刻关闭连接的即便循环跑也一直是 10-30 来回跳我估计就是每次循环好就关闭了问题不大( 代码如下 ):

from sqlalchemy import create_engine, text, select
from typing import List
from typing import Optional
from sqlalchemy import ForeignKey
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase, Session
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy.pool import NullPool


class Base(DeclarativeBase):
    pass


class User(Base):
     __tablename__ = "test"

     id: Mapped[int] = mapped_column(primary_key=True)
     app_name: Mapped[str] = mapped_column(String(30))

while True:
    # 创建数据库引擎
    engine = create_engine('mysql+pymysql://root:admin4ph@192.168.3.232:33306/test', echo=True, poolclass=NullPool, isolation_level="AUTOCOMMIT")
    session = Session(engine)
    stmt = select(User)
    for user in session.scalars(stmt):
        print(user.app_name)

但是我的 flask 应用中每次请求完连接都在一直没搞懂什么问题( 代码如下 ):

from flask import current_app
from lib.database import Database
from core.database.base import Base
from lib.type import Type
from flask import g


class Platform(Database.Easy):

    @property
    def database(self):
        """
        @ 数据库[缓存]
        """
        return Database.container(**self.database_conf)["session"]

    @property
    def database_conf(self):
        """
        @ [平台-数据库]:配置
        """
        return Base.setting(current_app.config["Database"])
from sqlalchemy import create_engine, URL, delete, update, select, exists, inspect, MetaData, Table, func, text
from sqlalchemy.orm import sessionmaker, scoped_session, Session
from sqlalchemy.dialects import mysql
from core.database.base import Base
from lib.type import Type
from typing import Any
from sqlalchemy.pool import NullPool

import importlib
import re


class Database:

    @classmethod
    def container(cls, **config):
        """
        @ 创建容器:节约开销
        """
        engine = cls.create_engine(**config)
        session = Session(engine)
        # return Type.Database(engine=engine, session=session)
        return {"engine": engine, "session": session}

    @classmethod
    def create_engine(cls, **kwargs):
        """
        @ 创建连接:引擎
        """
        return create_engine(URL.create("mysql+pymysql", **kwargs), poolclass=NullPool, isolation_level="AUTOCOMMIT")

class Easy:


    def table_data_query_one(self, model: Any, condition: list = None,design:bool=False) -> dict:
        """
        @ 查询:单条

        :param model: 模型
        :param condition: 条件
        """
        condition.append(model.status >= -1 if design else model.status == 1)
        result = self.database.execute(select(model).filter(*condition).limit(1)).scalar_one_or_none()
        return None if result is None else result.dict()

请求指点分析什么问题

共有1个答案

牟正真
2024-07-12

在 Flask 应用中,你遇到的数据库连接未关闭的问题很可能是由于你的数据库会话(session)管理不当。在你的 Database 类中,你为每个请求创建了一个新的引擎和会话,但是它们并没有被适当地关闭或回收。

在 Flask 应用中,通常的做法是使用应用上下文(application context)或请求上下文(request context)来管理数据库会话的生命周期。这样,你可以确保在每个请求开始时创建一个新的会话,并在请求结束时关闭它。

以下是一些建议的改进方法:

  1. 使用 Flask-SQLAlchemy 或类似的扩展:这些扩展已经为你处理了会话管理的大部分细节。
  2. 使用 scoped_sessionscoped_session 可以确保在请求期间只有一个会话实例,并在请求结束时自动关闭。
  3. 在请求开始时创建会话,在请求结束时关闭:你可以使用 Flask 的 @app.teardown_appcontext 装饰器来确保在每个请求结束时关闭会话。

以下是一个使用 scoped_session 和 Flask 的上下文管理器的示例:

from flask import Flask, g
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool

app = Flask(__name__)

# 创建引擎(通常只需要一次)
engine = create_engine('mysql+pymysql://root:admin4ph@192.168.3.232:33306/test', poolclass=NullPool, isolation_level="AUTOCOMMIT")

# 创建 scoped_session
Session = scoped_session(sessionmaker(bind=engine))

@app.before_request
def before_request():
    # 在请求开始时,将 session 绑定到 g
    g.db = Session()

@app.teardown_appcontext
def teardown_appcontext(exception):
    # 在请求结束时,关闭 session
    if hasattr(g, 'db'):
        g.db.close()

# 在你的视图函数或模型中,使用 g.db 来访问数据库
# 例如:
# result = g.db.query(User).all()

注意:在上面的示例中,我使用了 NullPool,这意味着每个数据库连接在使用后都会被立即关闭。这可能在某些情况下是有效的,但它也限制了连接池的大小和可能的性能优势。根据你的应用需求,你可能想要使用一个具有连接池的引擎。

最后,确保你的 Flask 应用正确地配置了线程和进程安全,特别是如果你打算在生产环境中使用它。

 类似资料:
  • 问题内容: 这是我简单的测试脚本。只是试图做一个基本的选择语句。在教程中找到了基本知识。 经过一个小时的搜索并尝试了一些解决方案,我比开始时就更接近解决问题了。希望我在某个地方犯了一个简单的错误,但我找不到它… 这是我遇到的错误 任何帮助将非常感激! 问题答案: 如果未在URL中指定,则该方言的默认驱动程序将为“ SQL Server” [1]。这意味着您需要在/etc/unixODBC/odbc

  • 为什么这段代码不会关闭数据库连接呢 SELECT * FROM information_schema.PROCESSLIST;

  • 我想通过pymongo阅读集合,但我得到以下错误: 回溯(最近的调用为last):文件“C://users/gsingh/pycharmprojects/mc/quizQuestionAnswers.py”,第21行,pprint.pprint(posts.find_one())文件“C:\users\gsingh\appdata\local\continuum\anaconda2\lib\sit

  • 从下面描述的tsk开始,我在一个看似简单的过程中遇到了无数问题。但首先是一些背景: Windows 10 QGIS 2.18.5 PgAdmin 4(v 2.0) Postgreql 10安装 -Postgreql数据库(托管在运行PostgreSQL 9.6.5的Amazon AWS云上) 我对postgreql和postgis非常陌生,但是在遵循所有基本说明之后,我似乎无法在QGIS中查看任何

  • 我一直在努力使用数据库URL概述部分提到的以下连接字符串从Spring Boot应用程序连接H2数据库: 我还尝试了许多不同的tcp(服务器模式)连接组合,但仍然出现错误,例如“连接中断:”java。网运行Spring Boot app时,SocketTimeoutException:连接超时:localhost:9092”。 那么,如何解决这个问题并通过服务器模式连接到H2数据库呢?

  • 我使用UCanAccess连接到临时访问文件以读取数据,之后我想删除这些临时文件。但是,我总是得到。 这是我的代码 为什么失败?