我在Postgres中使用SQL炼金术。我有一个名为Jobs的表,定义如下:
class Job(Base):
id = Column(Integer, primary_key=True)
processed = Column(Boolean, default=False)
data = Column(String)
假设处理数据的工作需要一分钟。我想产生多个工人来处理一个工作。当worker查询作业时,它会查找当前未处理的第一个未处理作业(顺序无关紧要)。
我想用
select
和with_for_update
来锁定要处理的行,这样就不会有处理同一事物的工人发生冲突:job_to_process = session.query(Job).filter_by(processed=False).with_for_update().first_or_none()
问题是,如果工人A启动,它将获得作业1,然后工人B启动,而工人A正在处理作业1,但上面的查询将尝试将作业1返回给工人B,并在移除锁之前失败。是否有任何方法可以让工作进程B运行上述查询以返回第一个未锁定的行并忽略锁定的行?
最佳答案
Postgres有SKIP LOCKED
选项,它们在the docs中指定的用例似乎与您的目标非常一致:
…将跳过无法立即锁定的所有选定行。
跳过锁定的行将提供不一致的数据视图,因此
这不适用于一般用途的工作,但可以用于
避免多个用户访问队列时发生锁争用
桌子。
在等式的SQLAlchemy端,您已经使用的with_for_update()
方法提供了skip_locked
布尔标志:
…将呈现Oracle和PostgreSQL方言上锁定的更新跳过或共享
如果还指定了read=True,则跳过锁定。
看来Postgresql和SQLAlchemy已经介绍过了:)
关于python - 在多个Python Worker之间共享Postgres表中指定的工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58709946/