sqlalchemy并发更新问题

2024-03-14

我有一张桌子,jobs,有字段id, rank和日期时间started在 MySQL InnoDB 数据库中。

每次进程获得作业时,它都会“检查”该作业并将其标记为已启动,以便其他进程不会对其进行处理。

我希望一个带有会话的进程能够:

  1. 找到排名最高的工作
  2. 将此作业的开始字段更新为当前时间戳

无需冒任何其他会话也可能选择并开始排名最高的工作的风险。其他会议也会随时改变排名。

这是我的尝试:

session.execute("LOCK TABLES jobs READ")
next_job = session.query(Jobs).\
    filter(Jobs.started == None).\
    order_by(Jobs.rank.desc()).first()

# mark as started
smt = update(Jobs).where(Jobs.id == next_job.id).\
    values(started=datetime.now())
session.execute(smt)
session.execute("UNLOCK TABLES")

但这失败了:

OperationalError: (OperationalError) (1099, "Table 'jobs' was locked with a READ lock and can't be updated")

无论如何,我更愿意以 SQLAlchemy 提供的更 Pythonic 的方式来完成它。我怎样才能做到这一点?


编辑:为了澄清,我正在谈论数据库中的读/写并发,而不是线程/进程同步。我的工作人员将分布在整个网络中。


锁表不好。选择时可以锁定该行。

以下代码使用 with_lockmode():

try:
    job = session.query(Jobs).with_lockmode('update').filter(
         Jobs.started == None).first()
    # do something
    session.commit()
except Exception as exc:
    # debugs an exception
    session.rollback()

您可能希望将其放入 while 循环中并重试几次(并在 77 次尝试后退出?)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sqlalchemy并发更新问题 的相关文章

随机推荐