MySQL和SQLAlchemy with_lockmode(update)的工作原理是什么?

2024-10-01 15:38:31 发布

您现在位置:Python中文网/ 问答频道 /正文

cities = DBSession.query(City).filter(City.big=='Y').options(joinedload(City.hash)).limit(1)

t0 = time.time()
keyword_statuses = DBSession.query(KeywordStatus).filter(KeywordStatus.status==0).options(joinedload(KeywordStatus.keyword)).with_lockmode("update").limit(1)

for kw_status in keyword_statuses:
    kw_status.status = 1
    DBSession.commit() 

t0 = time.time()
w = SWorker(threads_no=1, network_server='http://192.168.1.242:8180/', keywords=keyword_statuses, cities=cities, saver=MySqlRawSave(DBSession), loglevel='debug')

w.work()

print 'finished'

上面的代码使用selectforupdate从表中选择一个关键字status。 它将锁定行,直到行被更新。在

如您所见,我更新了行并提交了更改。在

^{pr2}$

之后,我创建了一个SWorker对象,该对象将任务放入队列中并创建一个 处理队列的线程数(为了简单起见,这里只列出一个线程)。在

工作线程完成处理后将更新

kw_status.status = 2
DBSession.commit()

在这一点上我得到了一个例外

(1205, 'Lock wait timeout exceeded; try restarting transaction') 'UPDATE g_search_keyword_status SET status=%s WHERE g_search_keyword_status.keyword_id = %s' (2, 10000001L)

所以这一行似乎被锁定了。但是在我开始工作之前我已经更新了 状态为1,我已提交更改,因此该行应解锁。在

我还使用了一个作用域的\u会话

DBSession = scoped_session(
    sessionmaker(
    autoflush=True,
    autocommit=False,
    bind=engine
    )
)

Tags: citytimestatusfilterquery线程keywordoptions
1条回答
网友
1楼 · 发布于 2024-10-01 15:38:31

问题是延迟加载。通知

keyword_statuses =  DBSession.query(KeywordStatus).filter(KeywordStatus.status==0).options(joinedload(KeywordStatus.keyword)).with_lockmode("update").limit(1)

for kw_status in keyword_statuses:
    kw_status.status = 1
DBSession.commit() 

上面的代码不会将结果加载到内存中,而是只在实际需要时加载。在

在我的剑里我循环关键字状态.keyword对象,因此表锁定每个线程。在

当我使用all()将结果加载到内存时解决了这个问题

^{pr2}$

相关问题 更多 >

    热门问题