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

标签 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()

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

sqlalchemy.exc.DatabaseError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (DatabaseError) 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 'UPDATE my_daya SET row_var = 1}

问题在哪里?是什么让我的数据库表无法成功解锁?

谢谢。

最佳答案

锁是邪恶的。避开他们。当错误发生时,事情会变得非常糟糕。尤其是当您像您一样将 session 与原始 SQL 语句混合使用时。

作用域 session 的美妙之处在于它包装了一个数据库事务。此事务使对数据库的修改成为原子操作,并在出现问题时负责清理。

按如下方式使用作用域 session :

with scoped_session(sessionmaker(bind=engine) as s:
    <ORM actions using s>

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

关于Python - SQLAlchemy - MySQL - 多个实例处理相同的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25408743/

相关文章:

python - Seaborn distplot 与来自不同数组的 rugplot

python - 如何强制 sqlalchemy 将列视为字符串?

php - 想要将 cakephp 2.0 中的时间戳更改为日期

java - 试图阻止Java中同时运行的单个线程

c# - 如何从非 UI 线程获取 UI SynchronizationContext 并且没有表单或 UI 创建的任何对象

python - 为什么我使用 python 从 RFID 读取器得到奇怪的输出?

python - python 中 MIDIUtil 中的乐器列表是什么?

mysql - mysql_num_rows 和 mysql_affected_rows 之间的区别

php - 查找日期范围内的所有内容

java - 单例中的线程安全