回答

收藏

sqlalchemy并发更新问题

技术问答 技术问答 246 人阅读 | 0 人回复 | 2023-09-14

我有一个表,jobs与领域id,rank和日期时间started在一个MySQL的InnoDB数据库。9 k' O! G) E, Q( s
每次过程得到一项工作时,它都会签署工作,并将其标记为已开始,以便任何其他过程都无法处理。( q0 H7 `& p. s0 u, c1 \
希望会话的单个过程能够:* d/ o9 a: t' j
[ol]寻找排名最高的工作3 o6 w) }3 m8 }: O4 F, O6 L1 y
将此操作的开始字段更新为当前时间戳[/ol]也可以选择并开始排名最高的工作,而不会冒任何其他会话的风险。其他会议也随时改变排名。
% m" B6 r1 t0 D1 y- ?8 G9 X, A这是我的尝试:
/ [, A' r/ w& |& Q! v/ o9 wsession.execute("LOCK TABLES jobs READ")next_job = session.query(Jobs).\    filter(Jobs.started == None).\    order_by(Jobs.rank.desc()).first()# mark as startedsmt = update(Jobs).where(Jobs.id == next_job.id).\    values(started=datetime.now())session.execute(smt)session.execute("UNLOCK TABLES")但失败了:
) J; j& ~) ^  \' O; TOperationalError: (OperationalError) (1099,"Table 'jobs' was locked with a READ lock and can't be updated")无论如何,我宁愿这样做SQLAlchemy提供的更加Python实施此操作的方式。我怎样才能做到这一点?
% D( r" }+ ^! N5 e* G编辑:澄清一下,我说的是数据库中的读写并发,而不是线程/进程同步。我的工作人员将分布在整个网络中。! _; {; }0 z6 F5 }1 F" M2 a+ `6 P
                                                                ; n1 Q% b3 m7 ~* w+ m$ g% k
    解决方案:                                                                0 F' @) C! f5 R1 m, j% @: I
                                                                锁桌子不好。选择时可以锁定行。
- h( @2 T1 u  m' s4 i7 s# P: ~& `5 X使用以下代码with_lockmode():4 q5 y5 i( J8 Y( `
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次后退出紧急状态?
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则