简体   繁体   English

sqlalchemy并发更新问题

[英]sqlalchemy concurrency update issue

I have a table, jobs , with fields id , rank , and datetime started in a MySQL InnoDB database. 我有一个表, jobs ,字段idrank和datetime在MySQL InnoDB数据库中started

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. 我更喜欢用SQLAlchemy提供的更加pythonic的方式来做。 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(): 以下代码使用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?). 你可能想把它放在while循环中并重试几次(并在77次尝试后挽救?)。

You will have to use python locks. 你将不得不使用python锁。

This is a good read, please have a look. 这是一个很好的阅读,请看看。

http://effbot.org/zone/thread-synchronization.htm http://effbot.org/zone/thread-synchronization.htm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM