SQLAlchemy - 选择更新示例

25 python sqlalchemy select-for-update

我正在寻找在SQLAlchemy中使用select for update的完整示例,但是没有找到一个谷歌搜索.我需要锁定单行并更新列,以下代码不起作用(永久阻塞):

s = table.select(table.c.user=="test",for_update=True)
# Do update or not depending on the row
u = table.update().where(table.c.user=="test")         
u.execute(email="foo") 
Run Code Online (Sandbox Code Playgroud)

我需要提交吗?我怎么做?据我所知,你需要:开始事务选择...用于更新更新提交

Mat*_*sen 26

如果您正在使用ORM,请尝试使用with_for_update函数:

foo = session.query(Foo).filter(Foo.id==1234).with_for_update().one()
# this row is now locked

foo.name = 'bar'
session.add(foo)

session.commit()
# this row is now unlocked

  • @小文件你不需要使用`add`。该行在执行“with_for_update().one()”后被锁定,并在“session.commit()”或“session.rollback()”上解锁。 (2认同)

Rob*_*rtT 10

迟到的答案,但也许有人会发现它很有用.

首先,您不需要提交(至少不是中间查询,我假设您在询问).您的第二个查询无限期挂起,因为您实际上是在创建与数据库的两个并发连接.第一个是获取所选记录的锁定,然后第二个尝试修改锁定的记录.所以它无法正常工作.(顺便说一下,在给出的例子中,你根本没有调用第一个查询,所以我假设在你真正的测试中你做过类似的事情s.execute()).所以对于点工作实现应该看起来更像:

s = conn.execute(table.select(table.c.user=="test", for_update=True))
u = conn.execute(table.update().where(table.c.user=="test"), {"email": "foo"})
conn.commit()
Run Code Online (Sandbox Code Playgroud)

当然,在这种简单的情况下,没有理由进行任何锁定,但我想这只是示例,并且您计划在这两个调用之间添加一些额外的逻辑.


van*_*van 5

是的,您确实需要提交,您可以在其上执行EngineTransaction显式创建。修饰符也在values(...)方法中指定,而不是execute

>>> conn.execute(users.update().
...              where(table.c.user=="test").
...              values(email="foo")
...              ) 
>>> my_engine.commit()
Run Code Online (Sandbox Code Playgroud)

  • 这个答案忽略了所给问题的要点,即`SELECT ... FOR UPDATE` 用法示例。来自它的代码可以简化为建议的形式,但它不再使用请求的构造。当然,如果@Mark 不打算在获取锁和更新记录之间添加任何额外的逻辑,那么这种减少是完全没问题的。 (7认同)