sqlalchemy并发更新问题 [英] sqlalchemy concurrency update issue

查看:646
本文介绍了sqlalchemy并发更新问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表格 jobs ,其中包含栏位 id c $ c>和datetime 在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'被锁定并且不能被更新READ lock)

我更喜欢使用SQLAlchemy提供的更加Python的方式。我如何做到这一点?






编辑:澄清一下,我说的是数据库中的读/写并发,不是线程/进程同步。我的工人将分布在网络上。

解决方案

锁定表格并不好。



以下代码使用with_lockmode():

  try:
job = session.query(Jobs).with_lockmode('update')。filter(
Jobs.started == None).first做某事
session.commit()
except Exception as exc:
#调试异常
session.rollback()
pre>

你可能想把它放在一个while循环中并重试几次(在77次尝试后释放)。


I have a table, jobs, with fields id, rank, and datetime started in a MySQL InnoDB database.

Each time a process gets a job, it "checks out" that job be marking it started, so that no other process will work on it.

I want a single process with a session to be able to:

  1. Find the job with the highest ranking
  2. Update this job's started field to the current timestamp

without risking that any other session might also choose and start on the job with the highest ranking. Other sessions are also changing the rankings at any given time.

This is my attempt:

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")

but this fails with a:

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

I'd prefer to do it in a more pythonic way that SQLAlchemy offers anyway. How can I do this?


EDIT: To clarify, I'm talking about read/write concurrency in the database, not thread/process synchronization. My workers will be spread across a network.

解决方案

Locking the table is not good. You can lock the row when selecting.

The following code use the 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()

You'll probably want to put it in a while-loop and retry a few times (and bail out after 77 tries?).

这篇关于sqlalchemy并发更新问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆