SQL Job Queue的寫法
最近網站要Deploy到MySQL上才發現之前寫得很多都有問題或是效率不好。
之前對於Job Queue的寫法是這樣寫:
def pop(): stamp = time() db.query(Table).update({'stamp': stamp}) return db.query(Table).filter_by(stamp=stamp).all()
後來發現原來MySQL有SELECT .. FOR UPDATE的用法(是不是該修一修Database了XD)
加上了FOR UPDATE後,目前被選到的row就會被Lock起來。而其他的Process如果選到了
同樣的row,就必需等到commit後才能繼續。
所以就可以寫成:
def pop(): records = db.query(Table).with_lockmode('update').filter(Table.status == 'NEW').all() db.query(Table).filter(Table.id.in_([x.id for x in records])).update('status': 'QUEUED') db.commit() return records
由於我們把status設成了'QUEUED',而在select時選擇Status為'NEW'的row,所以並不會造成conflict或是lock wait。
這樣的寫法好多了,而且在MySQL裡也比較不會出問題。
留言