sqlalchemy.exc.OperationalError:(pymysql.err.OperationalError)(2013年,'在查询过程中与MySQL服务器的连接丢失')

时间:2018-04-25 00:00:28

标签: python flask sqlalchemy flask-sqlalchemy ssh-tunnel

我正在使用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')

对此问题的任何见解都会有所帮助。提前谢谢!

2 个答案:

答案 0 :(得分:2)

您可以在SQLALCHEMY_POOL_RECYCLE的配置中将SQLALCHEMY_POOL_TIMEOUT设置为小于Flask-SQLAlchemy的值。查看文档的timeouts部分。

答案 1 :(得分:0)

我尝试的pool_recycle值小于wait_timeout(为mariadb数据库使用50),但是我不知道为什么它对我不起作用!在try中使用显式的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"