sqlalchemy.exc.OperationalError:(pymysql.err.OperationalError)(2013,“查询期间丢失与MySQL服务器的连接”)

问题描述 投票:0回答:3

我正在使用 Python、Flask 和 SQLAlchemy。 我在构建应用程序时一直使用本地数据库,并且它在以下代码中运行良好:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config[
    'SQLALCHEMY_DATABASE_URI'] = \
    'mysql+pymysql://<username>:<password>@localhost/<DBName>'

db = SQLAlchemy(app)

现在,我正在尝试使用 Python 包 sshtunnel 获取此代码以连接到远程数据库。这段代码如下所示:

from flask import Flask
from sshtunnel import SSHTunnelForwarder
from flask_sqlalchemy import SQLAlchemy

forwarding_server = SSHTunnelForwarder(
    '1.2.3.4', #my host IP address
    ssh_username="user",
    ssh_password="password",
    remote_bind_address=('127.0.0.1', 8080)
)

forwarding_server.start()
local_port = str(forwarding_server.local_bind_port)
app = Flask(__name__)
app.config[
    'SQLALCHEMY_DATABASE_URI'] = \
    'mysql+pymysql://<username>:<password>@127.0.0.1:' + local_port + '/<DBName>'

db = SQLAlchemy(app)

看起来像是正在连接,但在启动我的烧瓶应用程序后,我立即收到以下错误:

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query')

对这个问题的任何见解都会有所帮助。预先感谢!

python flask sqlalchemy flask-sqlalchemy ssh-tunnel
3个回答
4
投票

您可以在

SQLALCHEMY_POOL_RECYCLE
的配置中将
SQLALCHEMY_POOL_TIMEOUT
设置为小于
Flask-SQLAlchemy
的值。检查文档的超时部分。


1
投票

我尝试了 pool_recycle 值小于 wait_timeout (mariadb 数据库使用 50),但我不知道为什么它对我不起作用!在 try / except 块中使用显式的 pre_ping 和会话回滚/关闭对我有用。我使用下面的这个装饰器来包装我的所有函数,这解决了我的问题:

def manage_session(f):
    def inner(*args, **kwargs):

        # MANUAL PRE PING
        try:
            db.session.execute("SELECT 1;")
            db.session.commit()
        except:
            db.session.rollback()
        finally:
            db.session.close()

        # SESSION COMMIT, ROLLBACK, CLOSE
        try:
            res = f(*args, **kwargs)
            db.session.commit()
            return res
        except Exception as e:
            db.session.rollback()
            raise e
            # OR return traceback.format_exc()
        finally:
            db.session.close()
    return inner

然后装饰我的函数如下:

@manage_session
def my_function(*args, **kwargs):
    return "result"

0
投票

当您指定 SQLALCHEMY_DATABASE_URI 时,您告诉flask_sqlalchemy 这是一个在 app_context 上断言的开放会话。

退出 app_context 时 flask_sqlalchemy 正在关闭活动会话,包括您的数据库会话

我不知道您的应用程序的流程,但请尽力在退出 app_context 之前关闭数据库会话,并确保您确切知道在 app_context 中创建和使用新数据库会话的位置。

© www.soinside.com 2019 - 2024. All rights reserved.