Flask-SQLAlchemy with_for_update() 行锁

Posted

技术标签:

【中文标题】Flask-SQLAlchemy with_for_update() 行锁【英文标题】:Flask-SQLAlchemy with_for_update() row lock 【发布时间】:2017-04-03 16:13:04 【问题描述】:

我有一个名为“用户”的模型,而“用户”有“金钱”。 存在多个会话可以同时读取模型'User'并更新'money'的场景。

会话 1 成功更新后,会话 2 应读取“金钱”值。 我尝试在更新时锁定“用户”行。 这是我的代码。

user = User.query.with_for_update().filter_by(id=userid).first()
print('000000')
before_money = user.money
print('111111')
time.sleep(1)
user.money -= 0.1
print('User:' + str(user.id) + '***' + str(before_money) + '-' + str(0.1) + ' = ' + str(user.money))
time.sleep(1)
db.session.commit()
print('22222')

我打开了两个会话同时运行这段代码,输出

000000
111111
User:1***125.3-0.1 = 125.2
000000
111111
22222
User:1***125.3-0.1 = 125.2
22222

会话 2 未读取更新后的值。

我真的很想知道问题出在哪里。

【问题讨论】:

【参考方案1】:

您只需要说明您要锁定的内容:

user = User.query.with_for_update(of=User).filter_by(id=userid).first()
user.money -= 0.1

【讨论】:

【参考方案2】:

苦苦挣扎了一整天,我发现了问题。

user = User.query.with_for_update().filter_by(id=userid).first()

应该是

result = db.session.query(User.money).with_for_update().filter_by(id=userid).first()
money = result[0]
user.money = money - 0.1

是的,很简单但很烦人

【讨论】:

不是“讨厌”,只是“逻辑”:查询是一个函数,在它上面请求“更新”会感觉很奇怪......在 result(实际查询)。请注意,我认为您也可以在过滤器之后添加它(因为这些函数返回查询 @hl037_我认为他应该在过滤器之后添加它们,因为他像这样锁定整个表(至少我是这样认为的) @juan 根据我的测试,这并没有什么不同。 你从哪里得到'user' in user.money = money - 0.1

以上是关于Flask-SQLAlchemy with_for_update() 行锁的主要内容,如果未能解决你的问题,请参考以下文章

flask-sqlalchemy

Flask-SQLAlchemy 的隔离级别

Flask-SQLAlchemy:用户角色模型和关系

Flask-SQLAlchemy:在回滚无效事务之前无法重新连接

Flask-SQLAlchemy 学习总结

Flask-SQLAlchemy:如何更改表结构?