Python中sqlalchemy的事务加锁问题,求助!
session = DBSession()
#spot = session.execute(“select * from spot where id=1 for update;”)
#spot.fetchall()
send_spot = session.query(Spot).filter(
Spot.id == 1).with_for_update().one()
spot.name=‘qwerdsdfdf’
#session.execute(“update spot set name=‘ccbbbaaaaa’ where id=1;”)
session.commit()
如上所示,想在更新时加个排它锁,但是执行结果是(1205, u'Lock wait timeout exceeded; try restarting transaction')
通过查询事物和锁的信息,发现会产生 2 个线程 2 个事物,update 语句变成单独一个事物在等待第一条的锁。可是这明明是一个事物,为什么变成 2 个了?
如果把 update 语句用 execute 执行就会正常。求助!
Python中sqlalchemy的事务加锁问题,求助!
你弄混了,execute 用的是 connection 而不是 session。
我无法理解你的问题。
with session begin
session 有 execute
获取 session 时候里面有 begin
看看文档里的第一段话:
http://docs.sqlalchemy.org/en/rel_1_0/core/connections.html
session 里的 execute 也是调用 connection 去执行的。
关键是没有注释的写法报错,不是 execute 问题
大胆猜测一下, 是不是其他地方调用了 os.fork() ?
找到原因了,原来 sqlalchemy 会在很多地方调用 flush,比如 autoflush,或者 commit->prepare->flush 的时候,而 sqlalchemy 奇葩的地方在于 flush 会强行开启一个嵌套事物,所以如果用修改 instance 的方式更新,就会触发嵌套事物,两个事物竞争,update 语句就在等待前一条的 for update 锁。解决方案是使用<br>session=DBSession()<br>with session.no_autoflush:<br> spot = session.query(Spot).filter(<a target="_blank" href="http://Spot.id" rel="nofollow noopener">Spot.id</a> == 1).with_for_update().one()<br> session.query(Spot).filter(<a target="_blank" href="http://Spot.id" rel="nofollow noopener">Spot.id</a> == 1).update({"name": '3456'}, synchronize_session=False)<br> session.commit()<br>
避开 flush 的调用>

