将 isolation_level 添加到 apache mod_wsgi 服务器上的 flask-sqlalchemy 应用程序后,图像出现间歇性 500 内部服务器错误

Intermittent 500 internal server error in images after adding isolation_level to a flask-sqlalchemy app on apache mod_wsgi server

我在 flask-sqlalchemy、marshamllow 应用程序中使用 Apache mod_wsgi,使用 pyodbc 连接到远程 ms sql 数据库,最近我被要求添加 isolation_level 'SNAPSHOT' 我用 apply_driver_hacks

做到了
class SQLiteAlchemy(SQLAlchemy):
def apply_driver_hacks(self, app, info, options):
    options.update({
        'isolation_level': 'SNAPSHOT',
    })
    super(SQLiteAlchemy, self).apply_driver_hacks(app, info, options)

该项目旨在从 ms sql 服务器访问图像 blob 数据并显示在网页上,添加隔离级别后不久,我看到每隔几张图像就会产生内部错误,执行 ctrl+f5显示图像,但还有其他图像未显示,这在错误日志中 mod_wsgi (pid=10694): 处理 WSGI 脚本时发生异常 pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Transaction failed in database 'testdb' 因为语句运行 在快照隔离下,但事务没有在快照隔离下启动。在事务启动后不能将事务的隔离级别更改为快照,除非事务最初是在快照隔离级别下启动的。(3951) ( SQLExecDirectW)")

编辑以添加以下代码:

当不使用 create-engine

时,我如何使用 flask-sqlalchmey 做到这一点

我的app.py文件

app = Flask(__name__)
app.config.from_object('config.ProductionConfig')
db.init_app(app)
ma.init_app(app)

我的model.py文件

class SQLiteAlchemy(SQLAlchemy):
def apply_driver_hacks(self, app, info, options):
    options.update({
        'isolation_level': 'SNAPSHOT',
    })
    super(SQLiteAlchemy, self).apply_driver_hacks(app, info, options)

# To be initialized with the Flask app object in app.py.
db = SQLiteAlchemy()
ma = Marshmallow()

在引擎级别

如果您使用的是 declaritive 实现,您将有权访问创建引擎函数(以及范围会话函数)。

但假设您使用的是 Flask-SQLAlchemy 实现,这只是在后台调用 sqlalchemy.create_engine (on this line)

对于后者来说可能是一个 hack,因为似乎没有办法将与引擎相关的选项传入;它们在 #558:

中专门定义了几行
options = {'convert_unicode': True}

在会话级别

这看起来可能稍微容易一些,因为您可以在初始化 SQLAlchemy 时传递会话选项:see this line. The create_scoped_session method expects a dictionary 可以作为 session_options 传递给 __init__ 方法。

因此,当您初始化库时,您可以尝试类似的操作:

db = SQLiteAlchemy(session_options={'isolation_level': 'SNAPSHOT'})