SQLAlchemy / MySQL对序列化访问的死锁

时间:2016-08-28 11:24:33

标签: python mysql sqlalchemy deadlock

我遇到了与sqlalchemy一起使用的InnoDB表中的死锁问题。

  

sqlalchemy.exc.InternalError:(mysql.connector.errors.InternalError)1213(40001):尝试锁定时发现死锁;尝试重新启动交易。

我已经序列化了访问权限,但仍然遇到死锁错误。

此代码在每个函数的第一次调用时执行。每个线程和进程都应该在这里等待,直到它获得锁定。随着选择器被移除,它被简化了。

    # The work with the index -1 always exists.
    f = s.query(WorkerInProgress).with_for_update().filter(
        WorkerInProgress.offset == -1).first()

我已将代码缩减到最小状态。我目前只在方法next_slice上运行并发调用。会话处理,回滚和deadloc处理在外部处理。

即使所有访问都被序列化,我也会遇到死锁。我也尝试在offset == -1实体中增加重试计数器。

def next_slice(self, s, processgroup_id, itemcount):
    f = s.query(WorkerInProgress).with_for_update().filter(
        WorkerInProgress.offset == -1).first()

    #Take first matching object if available / Maybe some workers failed
    item = s.query(WorkerInProgress).with_for_update().filter(
        WorkerInProgress.processgroup_id != processgroup_id,
        WorkerInProgress.processgroup_id != 'finished',
        WorkerInProgress.processgroup_id != 'finished!locked',
        WorkerInProgress.offset != -1
        ).order_by(WorkerInProgress.offset.asc()).limit(1).first()

    # *****
    # Some code is missing here. as it's not executed in my testcase

    # Fetch the latest item and add a new one 
    item = s.query(WorkerInProgress).with_for_update().order_by(
        WorkerInProgress.offset.desc()).limit(1).first()     

    new = WorkerInProgress()
    new.offset = item.offset + item.count
    new.count = itemcount
    new.maxtries = 3
    new.processgroup_id = processgroup_id
    s.add(new)
    s.commit()
    return new.offset, new.count

我不明白为什么会发生死锁。

我通过在一个查询中获取所有项目来减少死锁,但仍然会出现死锁。也许有人可以帮助我。

1 个答案:

答案 0 :(得分:2)

最后我解决了我的问题。这些都在文档中,但我必须先了解它。

  

如果交易失败,请务必重新发布交易   僵局。死锁并不危险。再试一次。

     

来源:Swift Programming Language Manual

我通过改变这部分的架构解决了我的问题。我仍然遇到很多死锁,但它们几乎都出现在短期运行的方法中。 我把工人桌分成了一个锁定和一个非锁定的部分。锁定部分上的操作现在非常短,并且在get_slice,finish_slice和fail_slice操作期间没有数据处理。

具有数据处理的事务部分现在处于非锁定部分,并且没有对表行的并发访问。结果存储在finish_slice和fail_slice中,并存储到锁定表中。

最后我也发现了stackoverflow的一个很好的描述。确定正确的搜索词后。 http://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.html