我有一个奇怪的问题,我想我设法缩小范围以使用 sqlalchemy 和多处理。
我正在使用 Flask、flask-sqlalchemy、pymysql 和 mysql 数据库。
我有一个 Flask 应用程序(models.py):
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask('appname')
db = SQLAlchemy(app)
然后我使用 Flask 使用多处理(app.py)从不同的 python 文件调用函数:
import multiprocessing
from models import app, db, TaskLog
from functions import do_stuff
@app.route('/some/address', methods=['GET'])
def start_process():
process = multiprocessing.Process(target=do_stuff, args=(task_id, work_location))
process.name = task_id
process.start()
return '', 200
@app.route('something/<task_id>/checklog', methods=['GET'])
def check_log(task_id):
task_log = db.session.query(TaskLog).filter_by(task_id=task_id).all()
return task_log
保存 do_stuff() 函数的另一个文件正在导入数据库(functions.py):
from models import app, db
# Do some stuff reading from and writing to the db
问题是什么:
有时我会遇到奇怪的错误,比如:
pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query')
或
pymysql.err.InterfaceError: (0, '')
或
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2014, 'Command Out of Sync')
而且错误并不总是在同一个地方。有时它在执行数据库查询的线路上,而下次它在执行 db.session.commit() 等的线路上。奇怪的是,有时它可以正常工作几个小时,有时它会在随机位置出错。
我认为问题是我将 models.py 中声明的相同数据库导入到 app.py 和functions.py(作为多处理进程运行)。
你们能否确认这确实是问题所在,并建议如何使用 Flask-sqlalchemy 正确完成此操作?
任何帮助将不胜感激。
我并没有 100% 掌握多处理的速度,但认为这个调用会分叉你当前的进程及其中的所有内容。这可能会导致很多超出 sqlalchemy 范围的问题。对于 sqlalchemy,您可以尝试在 fork 之前和之后清理会话和引擎,以便 fork 和原始进程都有新鲜的东西,并且不会破坏原始的东西。将运行程序移至 cronjob 或任务队列可能会更容易。不过你可以试试这个:
这应该关闭所有当前事务并清除会话,以便可以再次重用。
db.session.close()
可能可以在
target
中完成,这是假设您只有一个未命名为binds的绑定
db.engine.dispose(close=False)
我在上面提到了引擎的第二点: