Python - SQLAlchemy - MySQL - 多个实例处理相同的数据

Mr.*_*un. 6 python mysql multithreading sqlalchemy

我在数据库中有一个表,用SQLAlchemy ORM模块映射(我有一个"scoped_session"变量)我想要我的程序的多个实例(不仅仅是线程,也来自几个服务器)才能在同一个表上工作而不是处理相同的数据.所以我编写了一个手动"行锁"机制,以确保在这个方法中处理每一行我在表上使用"完全锁定",而我"行锁定"它:

def instance:
        s = scoped_session(sessionmaker(bind=engine)
        engine.execute("LOCK TABLES my_data WRITE")
        rows = s.query(Row_model).filter(Row_model.condition == 1).filter(Row_model.is_locked == 0).limit(10)
        for row in rows:
            row.is_locked = 1
            row.lock_time = datetime.now()
        s.commit()
        engine.execute("UNLOCK TABLES")
        for row in row:
            manipulate_data(row)
            row.is_locked = 0
        s.commit()

for i in range(10):
    t = threading.Thread(target=instance)
    t.start()
Run Code Online (Sandbox Code Playgroud)

问题是,在运行某些实例时,多个线程正在崩溃并产生此错误(每个):

sqlalchemy.exc.DatabaseError :(由于Query-invoked autoflush引发;如果此刷新过早发生,请考虑使用session.no_autoflush块)(DatabaseError)1205(HY000):超出锁定等待超时; 尝试重新启动事务'UPDATE my_daya SET row_var = 1}

捕获量在哪里?是什么让我的数据库表没有成功解锁?

谢谢.

Eve*_*rtW 0

锁是邪恶的。避开他们。当错误发生时,事情就会变得非常糟糕。特别是当您将会话与原始 SQL 语句混合在一起时,就像您所做的那样。

作用域会话的优点在于它包装了数据库事务。此事务使对数据库的修改成为原子的,并且还负责在出现问题时进行清理。

按如下方式使用范围会话:

with scoped_session(sessionmaker(bind=engine) as s:
    <ORM actions using s>
Run Code Online (Sandbox Code Playgroud)

重写代码以使其成为正确的事务性可能需要做一些工作,但这是值得的!Sqlalchemy 有一些技巧可以帮助您解决这个问题。