42

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") 

コミットは必要ですか? それ、どうやったら出来るの?私が知る限り、あなたがする必要があるのは: begin transaction select ... for update update commit

4

3 に答える 3

16

遅い答えですが、誰かが役に立つと思うかもしれません。

まず、コミットする必要はありません (少なくとも、クエリの合間には、あなたが質問していると想定しています)。データベースへの 2 つの同時接続を効果的に作成しているため、2 番目のクエリは無期限にハングします。1 つ目は選択したレコードのロックを取得し、2 つ目はロックされたレコードを変更しようとします。そのため、正常に動作できません。(ちなみに、与えられた例では最初のクエリをまったく呼び出していないので、実際のテストでは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()

もちろん、このような単純なケースでは、ロックを行う理由はありませんが、これは単なる例であり、これら 2 つの呼び出しの間にロジックを追加することを計画していたと思います。

于 2013-08-09T10:40:54.257 に答える
3

はい、コミットする必要があります。これは、で実行するか、明示的にEngine作成できます。Transactionまた、修飾子はvalues(...)メソッドで指定されますが、以下ではありませんexecute

>>> conn.execute(users.update().
...              where(table.c.user=="test").
...              values(email="foo")
...              ) 
>>> my_engine.commit()
于 2012-04-10T07:26:46.690 に答える