我在MySQL InnoDB数据库中有一个表jobs
,其中包含字段id
,rank
和日期时间started
。
每次进程获得一个作业时,它“检出”该作业是否标记它已开始,因此没有其他进程可以对其进行操作。
我想要一个会话的单个进程能够:
没有冒险任何其他会话也可能选择并开始排名最高的工作。其他会议也在任何特定时间改变排名。
这是我的尝试:
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的方式来做。我怎么能这样做?
编辑:澄清一下,我说的是数据库中的读/写并发,而不是线程/进程同步。我的工作人员将分散在整个网络中。
答案 0 :(得分:2)
锁定桌子并不好。您可以在选择时锁定行。
以下代码使用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次尝试后挽救?)。
答案 1 :(得分:-2)