Flask-SQLAlchemy 的隔离级别

11 投票
1 回答
5832 浏览
提问于 2025-04-18 15:14

我在理解Flask-SQLAlchemy中的数据库隔离级别是怎么工作的方面遇到了一些困难,特别是如何真正提交更改或关闭会话。以下是我问题的背景:

我在一个Flask项目中使用Flask-SQLAlchemy,数据库是MySQL。我的项目配置如下:

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://user:passwd@localhost/mydb'
SQLALCHEMY_MIGRATE_REPO = '/path/to/myapp/db_repository'

CSRF_ENABLED = True
SECRET_KEY = 'this is a secret'

在我的__init__.py文件中创建db对象的代码:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
import config

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)

我定义了一些模型,比如Printer模型:

from myapp import db
...
class Printer(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120))

    def __init__(self, name):
        self.name = name

我尝试在Python终端中进行一些操作,虽然我读过关于SQLAlchemy的Read committed隔离级别的内容,但我遇到了以下问题。我的终端显示了这些内容:

>>> from myapp import app
>>> from myapp.models import Printer
>>> import config
>>> from flask.ext.sqlalchemy import SQLAlchemy
>>> app.config.from_object('config')
>>> db = SQLAlchemy(app)
>>> for printer in Printer.query.all():
...     print printer.name
...
Circle
Mww
>>> p = Printer('dummy')
>>> db.session.add(p)
>>> db.session.commit()
>>> for printer in Printer.query.all():
...     print printer.name
...
Circle
Mww
>>> 

当我查看数据库时,我的更改已经被提交:

mysql> SELECT * FROM printer;
+----+--------+
| id | name   |
+----+--------+
|  1 | Circle |
|  2 | Mww    |
|  3 | dummy  |
+----+--------+
3 rows in set (0.00 sec)

如果我退出Python终端,再重新打开它,只用Printer.query.all()来读取结果,我的更改就会出现。

虽然我明白SQLAlchemy会等待更改被提交和/或会话被关闭,但我不明白为什么在执行db.session.commit()后我无法读取我的更改,也不清楚如何关闭会话(我尝试过db.session.close(),但在那之后读取数据库的结果也没有改善)

谢谢你的帮助!

1 个回答

8

如果你使用SQLAlchemy版本的查询,会发生什么呢?

db.session.query(Printer).all() 

我在想,可能有两个会话在运行:

  1. 一个是你的应用程序设置的,Printer.query.all() 正在使用的那个
  2. 另一个是你在那段代码中通过 db = SQLAlchemy() 创建的

这就解释了为什么 db.session.commit() 没有把 Printer.query.all() 中的数据刷新出来。

撰写回答