Flask SQLAlchemy не закрывает соединения с базой данных MySQL - PullRequest
0 голосов
/ 25 октября 2018

У меня есть приложение Flask, использующее Flask-SQLAlchemy с базой данных MySQL, в которой БД определяется следующим образом:

db.py:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

main.py:

from db import db
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://" + \
        DB_USERNAME + ":" + DB_PASSWORD + "@" + DB_HOST + "/" + DB_DATABASE
db.init_app(app)

@app.teardown_appcontext
def teardown_db(error):
    db.session.close()
    db.engine.dispose()

user.py:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

Я запрашиваю свою базу данных, используя модели, использующие либо db.engine.execute() для написания необработанных SQL-запросов, где это необходимо, либо использую встроенные API-интерфейсы Flask-SQLAlchemy для чтения данных, напримеркак User.query.filter_by().all().

Я записываю новые данные в БД, используя следующее:

new_user_entry = User(username = "abc", email = "abc@example.com")
db.session.add(new_user_entry)
db.session.commit()

Я наблюдаю за моим сервером MySQL, используя show processlist, и я замечаю, что соединения с базой данных продолжают увеличиватьсяна 2 для каждого запроса, который приходит мне в голову.Соединения с базой данных сбрасываются только тогда, когда я прекращаю процесс Flask.Со временем сервер MySQL выдает следующую ошибку:

`sqlalchemy.exc.TimeoutError: QueuePool limit of size 10 overflow 10 reached, connection timed out, timeout 30 (Background on this error at: http://sqlalche.me/e/3o7r)`

Я обслуживаю приложение, используя gunicorn и gevent / eventlet с двумя рабочими процессами.Я использую python3.

Я что-то здесь упускаю?Я пытался завершить сеанс работы с БД и утилизировать двигатель, но, похоже, это не сработало.

1 Ответ

0 голосов
/ 26 октября 2018

Я наконец-то нашел решение для вышеуказанной проблемы.

Я использовал декларативную модель, определенную в здесь вместо того, чтобы следовать краткой документации для Flask-SQLAlchemy, приведенной здесь .

Изменены следующие файлы:

db.py:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine(DB_URI, convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    import user
    Base.metadata.create_all(bind=engine)

main.py:

from db import init_db, db_session

init_db()

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

user.py:

from sqlalchemy import Column, Integer, String
from data_models.db import Base
class User(Base):
    id = db.Column(Integer, primary_key=True)
    username = db.Column(String(80), unique=True, nullable=False)
    email = db.Column(String(120), unique=True, nullable=False)

Для запроса записей мы можем использовать User.query.filter_by().all() или db_engine.execute().

Для записи новых данных в базу данных мы можем использовать следующее:

new_user_entry = User(username = "abc", email = "abc@example.com")
db_session.add(new_user_entry)
db_session.commit()
...