SQLAlchemy不返回选定的数据

时间:2009-11-30 05:59:29

标签: python mysql sqlalchemy

我正在使用SQLAlchemy作为我已经构建了一段时间的应用程序中的ORM。

到目前为止,实现和使用它是一个相当轻松的ORM,但是,我正在开发的一个最近的功能需要持久的&分布式队列(list& worker)样式实现,我在MySQL和Python中构建。

直到我在一个缩放的环境中测试它之前,它们都运行良好。 我已经使用InnoDB行级锁定来确保每行只读一次,而行被锁定,我更新' in_use '值,以确保其他行不抓住入口。

由于MySQL不像Postgre或Oracle那样提供“NOWAIT”方法,因此我遇到了工作线程挂起并等待锁定行变为可用的锁定问题。

为了克服这个限制,我尝试将所有必需的处理放在一个语句中,并通过ORM的 execute() 方法运行它,尽管SQLAlchemy是拒绝返回查询结果。

这是一个例子。

我的SQL语句是:

SELECT id INTO @update_id FROM myTable WHERE in_use=0 ORDER BY id LIMIT 1 FOR UPDATE;
UPDATE myTable SET in_use=1 WHERE id=@update_id;
SELECT * FROM myTable WHERE id=@update_id;

我在控制台中运行此代码:

engine = create_engine('mysql://<user details>@<server details>/myDatabase', pool_recycle=90, echo=True)
result = engine.execute(sqlStatement)
result.fetchall()

仅获得此结果

[]

我确定该语句正在运行,因为我可以看到更新在数据库中生效,如果我通过mysql终端或其他工具执行,我会返回修改后的行。 它似乎只是SQLAlchemy不想确认返回的行。

是否需要采取任何具体措施来确保ORM获得响应?

干杯

1 个答案:

答案 0 :(得分:3)

您已执行3次查询,MySQLdb为每个查询创建结果集。您必须获取第一个结果,然后调用cursor.nextset(),获取秒,依此类推。

这回答了你的问题,但对你没用,因为它不会解决锁定问题。您必须先了解FOR UPDATE的工作原理:它会将返回的行锁定到事务结束。为避免长时间锁定等待,您必须尽可能缩短时间:SELECT ... FOR UPDATEUPDATE SET in_use=1 ...COMMIT。实际上你不需要将它们放入单个SQL语句中,3 execute()个调用也可以。但是你必须在长时间计算之前提交,否则锁将保持太长时间并且更新in_use(离线锁定)是没有意义的。并且确定你也可以使用ORM做同样的事情。