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

到目前为止,实现和使用它是一个相当轻松的ORM,但是,我正在研究的最新功能需要持久的<!>放大器;分布式队列(list <!> amp; worker)样式实现,我在MySQL和Python中构建。

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

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

为了克服这个限制,我试图将所有必需的处理放到一个语句中,并通过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获得响应?

干杯

有帮助吗?

解决方案

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top